Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheriting and aggregating class attributes

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:

  1. Ignore that disconcerting feeling and copy everything by hand.
  2. 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.

  3. 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 ModelForms but want to extend it. I don't think the inherited class should need to duplicate the ModelForms 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?

like image 892
jozxyqk Avatar asked Oct 19 '25 22:10

jozxyqk


1 Answers

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 }.

like image 130
nu11p01n73R Avatar answered Oct 22 '25 12:10

nu11p01n73R



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!