Inheriting and Combining Class Attributes
Simple example:
class A:
attr = {'a': 1}
class B(A):
attr = {'b': 2} #overrides A.attr
What I want is a dictionary aggregation method. I can only think of these options:
- Ignore this unpleasant feeling and copy everything by hand.
-
Manually adding dictionaries:
class B(a): attr = dict(list(six.iteritems(A.attr)) + list(six.iteritems({ 'b': 2 })))
Note
'b': 2
should be the second, so its keys will be shadowA
.It should state it explicitly
A
( is there a way to get this usingsuper
? ). It also needs micro-inheritance to be applied manually. -
This can also be achieved with metaclasses. I've seen this done
DeclarativeFieldsMetaclass
in django . The idea is to merge the metaclass dictionary for a specific attribute.This is much more work. Also, since it introduces magic that doesn't normally happen in python, it might be considered a bad option. I also prefer not to use metaclasses if needed to avoid conflicts.
One of the main advantages is that the user does not need to manually aggregate the attribute data.
Is there another way?
I would like to know what others think of each approach regarding good programming practice.
In my case I am using MultiModelForm
from django-betterforms and has a basic form with several ModelForm
but want to expand it. I don't think that the inherited class should duplicate ModelForm
in the attribute form_classes
from the parent.
Should the user manage inheritance as in Option 2, or should it MultiModelForm
handle it automatically with a metaclass as in Option 3? Are there other issues with each option that I haven't discussed?
source to share
You can do this using a dictionary.update()
function that will add a new dictionary to the existing one
Example
>>> class A:
... attr = {'a': 1}
...
>>> class B(A):
... attr = dict(A.attr)
... attr.update({'b' : 2 })
...
>>>
>>> A.attr
{'a': 1}
>>> B.attr
{'a': 1, 'b': 2}
What is he doing?
-
attr = dict(A.attr)
returns a new dictionary fromA.attr
. This is important because if we writeattr = A.attr
we will end up updating the
attr
classA
instead of the classB
. -
attr.update({'b' : 2 })
UpdatesB.attr
by adding a new dictionary{'b' : 2 }
.
source to share