Python元类混淆

时间:2014-02-09 13:05:51

标签: python

在多重继承的情况下,我对元类有点困惑。

请考虑以下代码:

class MetaClass1(type):
    def __init__(cls, name, bases, dict_):
        print "MetaClass1"

class MetaClass2(type):
    def __init__(cls, name, bases, dict_):
        print "MetaClass2"

class A(object):
    __metaclass__ = MetaClass1


class B(object):
    __metaclass__ = MetaClass2

class C(A, B):
    pass

输出结果如下:

  1. “MetaClass1”

  2. “MetaClass2”

  3. 关于元类冲突的TypeError,预计没有问题。

  4. 接下来,我将更改代码并执行以下操作:

    class MetaClass1(type):
        def __init__(cls, name, bases, dict_):
            print "MetaClass1"
    
    class MetaClass2(MetaClass1):
        def __init__(cls, name, bases, dict_):
            print "MetaClass2 inherits"
            super(MetaClass2, cls).__init__(name, bases, dict_)
    
    class A(object):
        __metaclass__ = MetaClass1
    
    
    class B(object):
        __metaclass__ = MetaClass2
    
    class C(A, B):
        pass
    

    这次输出将是:

    1. “MetaClass1”

    2. “MetaClass2继承”

      “MetaClass1”

    3. “MetaClass2继承”

      “MetaClass1”

    4. C级的MRO是:

      [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>]
      

      为什么C类接收MetaClass2作为其元类而不是MetaClass1?

1 个答案:

答案 0 :(得分:5)

在决定没有明确指定类的类的元类时,如同C的情况一样,Python检查正在创建的类的所有超类(直接和间接)的元类,并选择一个元类,它是正在创建的类的超类的所有元类的子类型。如果没有这样的元类,则会引发TypeError

在您的示例中,MetaClass2是一个继承自C超类的所有元类的元类。

这在语言参考的section 3.3.3.1中有所介绍。