Imagine we have a class Animal with a class attribute info
, which is a dictionary. There is a class Frog which inherits from Animal and also has a class attribute info
. But the attribute info
of the Frog class must also include the Animal info.
class Animal:
info = {'one':1, 'two':2}
class Frog(Animal):
info = {'three':3}
assert 'three' in Frog.info
I can use @property
class Frog(Animal):
_info = {'three':3}
@property
def info(self):
return self._info | Frog.info
But this is just fragile. Do the large Python library includes any Class that doesn't overwrite the Class attributes?
CodePudding user response:
If you want the info
values to be automatically merged by subclasses, you will need to use a metaclass to achieve this.
The metaclass is code which can modify the class definition, so it can look at the value of info
on the parent class and the value of info
in the sub-class as it is being defined ... and it can merge them and set the result of that as the value of info
in the resulting sub-class.
It would look like this:
class MergeInfoMetaclass(type):
def __new__(metacls, name, bases, attrs):
base_info = {}
for base in bases:
try:
base_info.update(base.info)
except AttributeError:
continue
try:
info = attrs["info"]
except KeyError:
pass
else:
attrs["info"] = base_info | info
return super().__new__(metacls, name, bases, attrs)
class Animal(metaclass=MergeInfoMetaclass):
info = {'one': 1, 'two': 2}
class Frog(Animal):
info = {'three': 3}
class GoldenTreeFrog(Frog):
info = {'four': 4}
assert Animal.info == {'one': 1, 'two': 2}
assert Frog.info == {'one': 1, 'two': 2, 'three': 3}
assert GoldenTreeFrog.info == {'one': 1, 'two': 2, 'three': 3, 'four': 4}
CodePudding user response:
You can refer to the parent's attribute in the child.
class Frog(Animal):
info = Animal.info {'three': 3}