用元类继承类字典

Pro*_*e85 5 python inheritance metaclass python-3.x

我正在fields使用元类设置类属性:

class MyMeta(type):
    def __new__(mcs, name, bases, clsdict):

        clsdict['fields'] = {k: v
                             for k, v in clsdict.items()
                             if <my_condition>}
        return super(MyMeta, mcs).__new__(mcs, name, bases, clsdict)

class MyBaseClass(metaclass=MyMeta):
    fields = {}
Run Code Online (Sandbox Code Playgroud)

以下实例化导致预期结果:

class SubClass(MyBaseClass):
    param1 = 1 # meets <my_condition>

>>> SubClass.fields
{param1: 1}
Run Code Online (Sandbox Code Playgroud)

但如果我现在子类SubClass,fields是空的:

class SubSubClass(SubClass):
   pass

>>> SubSubClass.fields 
{}
Run Code Online (Sandbox Code Playgroud)

我如何能够更新继承层次结构中所有类的 classdict 以便fields从基类更新变量?

MSe*_*ert 5

您需要以某种方式保留fields超类,例如通过迭代“基础”并使用它们fields作为起点:

class MyMeta(type):
    def __new__(mcs, name, bases, clsdict):
        if 'fields' not in clsdict:
            clsdict['fields'] = {}
        # Initialize "fields" from base classes
        for base in bases:
            try:
                clsdict['fields'].update(base.fields)
            except AttributeError:
                pass
        # Fill in new fields (I included a "trivial" condition here, just use yours instead.)
        clsdict['fields'].update({k: v for k, v in clsdict.items() if k.startswith('param')})
        return super(MyMeta, mcs).__new__(mcs, name, bases, clsdict)
Run Code Online (Sandbox Code Playgroud)

它适用于SubClassSubSubClass

>>> SubClass.fields
{'param1': 1}

>>> SubSubClass.fields
{'param1': 1}
Run Code Online (Sandbox Code Playgroud)

  • @ProfHase85:因为一个子类可以有多个基类,其中一些可能没有“fields”属性。 (2认同)