【问题标题】:python metaclasses of classes created by type按类型创建的类的python元类
【发布时间】:2013-05-16 10:28:40
【问题描述】:

这里的代码胜过文字:

class MetaA(type):
    def __new__(cls, name, bases, attrs):
        print "MetaA"
        return super(MetaA, cls).__new__(cls, name, bases, attrs)


class A(object):
    __metaclass__ = MetaA

这将打印MetaA

class MetaB(MetaA):
    def __new__(cls, name, bases, attrs):
        print "MetaB"
        return super(MetaB, cls).__new__(cls, name, bases, attrs)


B = type('B', (A, ), {'__metaclass__': MetaB})

这将再次打印MetaA (?!)

我希望:

MetaB
MataA

问题是:

  1. 为什么我只收到MetaA
  2. 如何更改代码获取:

    MetaB
    MataA
    

【问题讨论】:

    标签: python oop python-2.7 metaprogramming metaclass


    【解决方案1】:

    原因是type(name, bases, dict) 不是创建具有指定元类的类的正确方法。

    解释器实际上避免在看到__metaclass__ 属性定义并调用mateclass 而不是 type(name, bases, dict) 时调用type(name, bases, dict),因为它通常会这样做。

    这里是相关的docs section 解释它:

    读取类定义时,如果定义了__元类__则 分配给它的可调用对象将被调用而不是 type()。这 允许编写类或函数来监视或更改 类创建过程 [...]

    如果你像这样修改你的代码:

    class MetaA(type):
        def __new__(cls, name, bases, attrs):
            print "MetaA"
            return super(MetaA, cls).__new__(cls, name, bases, attrs)
    
    class A(object):
        __metaclass__ = MetaA
    
    
    class MetaB(MetaA):
        def __new__(cls, name, bases, attrs):
            print "MetaB"
            return super(MetaB, cls).__new__(cls, name, bases, attrs)
    
    class B(A):
        __metaclass__ = MetaB
    

    ...然后你会得到预期的输出:

    MetaA
    MetaB 
    MetaA 
    

    (创建A类时打印第一行,创建B类时打印第二行和第三行)

    更新:该问题假定类 B 的动态创建,所以我将扩展我的答案。

    要使用 metacalss 动态构造 B 类,您应该做与解释器相同的事情,即使用 __metaclass__ instad of type(name, bases, dict) 中的元类构造类。

    像这样:

    B = MetaB('B', (A, ), {'__metaclass__': MetaB})
    

    【讨论】:

    • 你说对了一部分,但你没有抓住重点。我使用“类型”的原因是因为我有很多想要动态创建的类。但是由于 'type' 是元类,应该写 MetaB('B', (A, ), {'metaclass': MetaB}) 而不是 type('B', (A, ), {' 元类':元B})。我昨天已经想通了。如果您更改答案以反映我的要求(动态创建的类),我会接受您的回答。
    • @mnowotka 啊,明白了。这就是您首先使用type 的原因。我已经更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2012-06-27
    • 2021-04-01
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2018-10-25
    • 2019-05-19
    • 1970-01-01
    相关资源
    最近更新 更多