【发布时间】:2016-09-21 11:55:37
【问题描述】:
在这个众所周知的answer 中解释了 Python 中的元类。它提到__metaclass__属性不会被继承。
但事实上,我在 Python 中尝试过:
class Meta1(type):
def __new__(cls, clsname, bases, dct):
print "Using Meta1"
return type.__new__(cls, clsname, bases, dct)
# "Using Meta1" printed
class Foo1:
__metaclass__ = Meta1
# "Using Meta1" printed
class Bar1(Foo1):
pass
正如预期的那样,Foo 和 Bar 都使用 Meta1 作为元类并按预期打印字符串。
但在以下示例中,当返回 type(...) 而不是 type.__new__(...) 时,元类不再被继承:
class Meta2(type):
def __new__(cls, clsname, bases, dct):
print "Using Meta2"
return type(clsname, bases, dct)
# "Using Meta2" printed
class Foo2:
__metaclass__ = Meta2
# Nothing printed
class Bar2(Foo2):
pass
检查__metaclass__和__class__属性,我可以看到:
print Foo1.__metaclass__ # <class '__main__.Meta1'>
print Bar1.__metaclass__ # <class '__main__.Meta1'>
print Foo2.__metaclass__ # <class '__main__.Meta2'>
print Bar2.__metaclass__ # <class '__main__.Meta2'>
print Foo1.__class__ # <class '__main__.Meta1'>
print Bar1.__class__ # <class '__main__.Meta1'>
print Foo2.__class__ # <type 'type'>
print Bar2.__class__ # <type 'type'>
总结:
__metaclass__和__class__将从基类继承。Meta2定义的创建行为将用于Foo2,虽然Foo2.__class__实际上是type。Bar2中的__metaclass__属性为Meta2,但Bar2的创建行为不受影响。换句话说,Bar2使用type作为它的“真实”元类,而不是Meta2。
这些观察使__metaclass__ 的继承机制对我来说有点模糊。
我的猜测是:
当直接将一个类(例如
Meta1)赋值给另一个类'Foo1'的__metaclass__属性时,是__metaclass__属性生效。当子类在定义时没有显式设置
__metaclass__属性。基类的__class__属性而不是__metaclass__属性将决定子类的“真实”元类。
我的猜测正确吗? Python如何处理元类的继承?
【问题讨论】:
-
我认为这与 type.__new__ 和输入 stackoverflow.com/questions/2608708/… 有关
标签: python inheritance python-2.x metaclass