Python元类的执行顺序测试
在stackoverflow上关于元类的高票答案中提到了Python中的元类的优先次序为
- 是否在Foo中有__metaclass__属性?如果有,在内存中通过使用__metaclass__中指定的和Foo这个名字创建类对象。
- 如果找不到__metaclass__,Python将会使用Bar(Foo的第一个父类)的metaclass(可能是默认的type)来创建类对象。
- 如果Python找不到__metaclass__,Python将会在模块层次寻找__metaclass__,并且尝试做相同的事情(仅仅对没有继承任何类的类,基本上都是old-style classes 基本上可以认为是没有继承object的类,super就不适用于old-style classes)
现在测试如下:
class MetaClassTest1class(type):
def __new__(cls, clsname, bases, dct):
dct['test'] = 1
return super(MetaClassTest1class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest2class(type):
def __new__(cls, clsname, bases, dct):
dct['test'] = 2
return super(MetaClassTest2class, cls).__new__(cls, clsname, bases, dct)
__metaclass__ = MetaClassTest1class
class Foo():
__metaclass__ = MetaClassTest2class
pass
f = Foo()
print f.test
输出为2,所以会优先调用自己的__metaclass__
对于2,
class MetaClassTest1class(type):
def __new__(cls, clsname, bases, dct):
dct['test'] = 1
return super(MetaClassTest1class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest2class(type):
def __new__(cls, clsname, bases, dct):
dct['test'] = 2
return super(MetaClassTest2class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest3class(MetaClassTest2class):
def __new__(cls, clsname, bases, dct):
dct['test'] = 3
return super(MetaClassTest3class, cls).__new__(cls, clsname, bases, dct)
__metaclass__ = MetaClassTest1class
class Foo():
__metaclass__ = MetaClassTest2class
pass
class FooChild(Foo):
pass
f = Foo()
print f.test
输出为2,所以在自己没有__metalcass__的情况下,看起来会使用父类的__metaclass__
对于3,
class MetaClassTest1class(type):
def __new__(cls, clsname, bases, dct):
dct['test'] = 1
return super(MetaClassTest1class, cls).__new__(cls, clsname, bases, dct)
__metaclass__ = MetaClassTest1class
class Foo():
pass
class FooChild(Foo):
pass
f = Foo()
print f.test
输出为1,所以可以看到,在自身没有元类,父类没有元类的时候会使用模块中的元类。