I have a hierarchy of entities that should contain dictionaries with metadata. Any sub-class should inherit its ancestor dictionary and be able to add some key-values (delete inherit keys is not needed). The easiest solution I can think about is this:class A(object):    def __init__(self):        self.doc = A.generate_doc()    @staticmethod    def generate_doc():         return {'a': 0}class B(A):    def __init__(self):        super().__init__()        self.doc.update(B.generate_doc())    @staticmethod    def generate_doc():        return {'b': 0}class C(B):    def __init__(self):        super().__init__()        self.doc.update(C.generate_doc())    @staticmethod    def generate_doc():        return {'c': 0}print(A().doc)  # {'a': 0}print(B().doc)  # {'a': 0, 'b': 0}print(C().doc)  # {'a': 0, 'b': 0, 'c': 0}Is this a good design? Could the update() blocks be implicit maybe? I have more than one document in real code, so that would be nice.
Python class hierarchy, extend ancestor data
python;object oriented;dictionary
Is this a good design?No IMO it's quite horrible, please reconsider it.Could the update() blocks be implicit maybe?Yeah, use metaclasses.I have more than one document in real code, so that would be nice.Yeah, don't request us to write code for you. However, with a metaclass this is easy.To make a cross Python 2 and Python 3 metaclass you need to use something like Class = Class('name', (object,), {}).You want to also build these dictionaries in the metaclasses __new__, and for the values to be taken from another attribute.To do this I defaulted to the uppercase of the value. I.e. A.DOC.This works kinda like Python's default multiple inheritance, but I make no guarantees. Also doc is now a static value, so you may need to clone it at object instantiation.def update(values=[]):    if isinstance(values, str):        values = values.split()    class Meta(type):        def __new__(meta, classname, bases, class_dict):            for value in values:                val = {}                for base in reversed(bases):                    val.update(getattr(base, value, {}))                val.update(class_dict.get(value.upper(), {}))                class_dict[value] = val            return super(Meta, meta).__new__(meta, classname, bases, class_dict)    return Meta('Meta', (object,), {})class A(update('doc')):    DOC = {'v': 0}class B(A):    DOC = {'v': 1}class C(A):    DOC = {'c': 0}class D(B, C):    passclass E(C, B):    passprint(D.doc)print(E.doc)