Overriding class attribute: keep changes to parent class
I want two classes. Class A with a default class attribute and class B (child class) that override this class attribute. But if the definition of the attribute of class A is changed by the developer, I don't want to write the attribute of class B again.
Example: with a simple override:
class Animal:
actions = {}
class Dog(Animal):
actions = {'bite': 1}
If the day Animal
changes as follows:
class Animal:
actions = {'bleed': 1}
The dog class needs to be rewritten. So I do this to prevent the parent class from being updated:
Python 3.4.0 (default, Apr 11 2014, 13:05:18)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
... d = {}
... @classmethod
... def c(cls):
... print(cls.d)
...
>>> class B(A):
... d = A.d.copy()
... d.update({0: 1})
...
>>> B.c()
{0: 1}
>>> A.c()
{}
Is this a good way to do it? Or is there still a "python way" to do this?
source to share
Copying attributes in a class method
By using copy
, you provide A
d
, no matter who / who defines it, will be the starting point before B
continuing with it.
class A:
d = {}
@classmethod
def c(cls):
print (cls.d)
class B(A):
d = A.d.copy()
d.update({0:1})
B.c()
A.c()
Output
{0: 1}
{}
The developer's changes A
at a later time are B
received A
without touching the definition B
.
class A:
d = {2:3}
@classmethod
def c(cls):
print (cls.d)
class B(A):
d = A.d.copy()
d.update({0:1})
B.c()
A.c()
Output
{0: 1, 2: 3}
{2: 3}
Warning. If it d
contains other objects inside it, you can use copy.deepcopy
, otherwise only the first "level" will be copied, all other objects will be references to the original (this caused me a lot of grief once before I knew about it!).
Instance method inheritance
Dictionary-copying is pythonic in the sense that it is clear what B
gets A
and extends it, but since you will probably be instantiating in your use case (for example Dog
), these classes might not be able to use the concept of a class instance with a method __init__
. This will allow you to have multiple B
s with potentially unique d
s.
Here is an example of instance-aware class definitions
class A:
def __init__(self):
self.d = {}
def c(self):
print (self.d)
class B(A):
def __init__(self):
A.__init__(self)
self.d.update({0:1})
# create instances of each class
a = A()
b1 = B()
b2 = B()
# call each instance c method
b1.c()
b2.c()
a.c()
# you can even update on the fly without affecting the other!
a.d.update({2:3})
b1.d.update({4:5})
b2.d.update({7:8})
b1.c()
b2.c()
a.c()
Output
{0: 1}
{0: 1}
{}
{0: 1, 4: 5}
{0: 1, 7: 8}
{2: 3}
source to share