代码优于此处的文字:
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
问题是:
MetaA
?如何更改代码:
MetaB
MataA
答案 0 :(得分:1)
原因是type(name, bases, dict)
不是使用指定元类创建类的正确方法。
解释器实际上避免在看到type(name, bases, dict)
属性定义时调用__metaclass__
,并像通常那样调用mateclass 而不是 type(name, bases, dict)
。
以下是解释它的相关docs section:
读取类定义时,如果定义了__元类__ 分配给它的callable将被调用而不是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__
type(name, bases, dict)
的{{1}}实例中构造具有元类的类。
像这样:
B = MetaB('B', (A, ), {'__metaclass__': MetaB})