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?

+3


source to share


1 answer


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}

      

+1


source







All Articles