Reputation: 17266
A simple example:
class A:
attr = {'a': 1}
class B(A):
attr = {'b': 2} #overrides A.attr
What I want is a method to aggregate the dictionaries. I can think of just these options:
Manually adding the dictionaries:
class B(a):
attr = dict(list(six.iteritems(A.attr)) + list(six.iteritems({
'b': 2
})))
Note 'b': 2
must come second so its keys shadow A
's.
This must reference A
explicitly (is there some way to get this with super
?). It also needs this kind of micro inheritance to be applied manually.
This is also something that could be achieved with metaclasses. I've seen it done in DeclarativeFieldsMetaclass
in django.
The idea is to have the metaclass handle dictionary merging for a specific attribute.
This is far more work. Also, as it introduces magic that doesn't normally happen in python, this might be considered a poor option. I also prefer to not use metaclasses unless necessary to avoid conflicts.
One major advantage is the user doesn't need to manually aggregate the attribute data.
Is there another way?
I'd like to know what others think of each approach with regard to good programming practice.
In my case I'm using a MultiModelForm
from django-betterforms, and have a base form with just a few ModelForm
s but want to extend it. I don't think the inherited class should need to duplicate the ModelForm
s in the form_classes
attribute from the parent.
Should it be up to the user to manage inheritance as in option 2 or should MultiModelForm
handle it automatically with a metaclass as in option 3? Are there other issues with each option I haven't discussed?
Upvotes: 4
Views: 147
Reputation: 26667
You can do it using dictionary.update()
function, which will add a new dictionary to an 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 it does?
attr = dict(A.attr)
returns a new dictionary from A.attr
. This is important because if we write
attr = A.attr
we will end up updating the attr
of A
class instead of B
class.
attr.update({'b' : 2 })
Updates the B.attr
by adding the new dictionary {'b' : 2 }
.
Upvotes: 7
Reputation: 206577
This works for me:
class A:
attr = {'a': 1}
class B(A):
attr = dict({'b': 2}.items() + A.attr.items())
Upvotes: 4