Reputation: 7789
I want two class. Class A with a default class attribute and class B (child class) who override this class attribute. But if A class attribute definition is changed by developper, i don't want to write again B class attribute.
Exemple: With simple override:
class Animal:
actions = {}
class Dog(Animal):
actions = {'bite': 1}
If a day, Animal
is modified like this:
class Animal:
actions = {'bleed': 1}
Dog class have to be rewrited. So i do that to prevent parent class update:
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 a more "python way" to do it?
Upvotes: 4
Views: 4559
Reputation: 10758
By using copy
you are ensuring A
's d
, no matter what/who defines it, will be the starting point before B
extends 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}
{}
developer changes A
at a later time, B
gets A
without touching B
's definition.
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 d
contains other objects inside it, you may want to use copy.deepcopy
, otherwise only the first "level" will be copied, all others objects will be references to the original (this caused me a lot of grief once, before I knew about it!).
The dictionary copying is pythonic in the sense that it is clear that B
gets A
and extends it, but since you will probably be creating instances in your use case (of say Dog
), these classes might be missing the concept of a class instance by using the __init__
method. This will allow you to have multiple B
s with potentially unique d
s.
Here is an example of class definitions with an instance in mind
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's 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}
Upvotes: 3