继承中的元类
首先写代码测试的时候发现问题
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(type):
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):
__metaclass__ = MetaClassTest3class
pass
f = Foo()
print f.test
运行的结果是
TypeError Traceback (most recent call last)
<ipython-input-52-81f8a2dedcb4> in <module>()
24 pass
25
---> 26 class FooChild(Foo):
27 __metaclass__ = MetaClassTest3class
28 pass
<ipython-input-52-81f8a2dedcb4> in __new__(cls, clsname, bases, dct)
18 dct['test'] = 3
19
---> 20 return super(MetaClassTest3class, cls).__new__(cls, clsname, bases, dct)
21
22 class Foo():
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
也就是子类的元类必须是所有的父类元类的子类(但是并不要求是直接子类)!而这里我们的FooChild的元类为MetaClassTest3class,并不是Foo的元类的子类。修改MetaClassTest3class为MetaClassTest2class的子类,同时我们在元类中进行输出,查看元类具体的运行过程
class MetaClassTest1class(type):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest1class test in dct', dct['test']
dct['test'] = 2
dct['test'] = 1
print dct['test']
return super(MetaClassTest1class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest2class(type):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest2class test in dct', dct['test']
dct['test'] = 2
print 'MetaClassTest2class', dct['test']
return super(MetaClassTest2class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest3class(MetaClassTest2class):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest3class test in dct ', dct['test']
dct['test'] = 3
print 'MetaClassTest3class', dct['test']
return super(MetaClassTest3class, cls).__new__(cls, clsname, bases, dct)
__metaclass__ = MetaClassTest1class
class Foo():
__metaclass__ = MetaClassTest2class
pass
class FooChild(Foo):
__metaclass__ = MetaClassTest3class
pass
f = FooChild()
print 'final test val', f.test
输出为
MetaClassTest2class 2
MetaClassTest3class 3
MetaClassTest2class test in dct 3
MetaClassTest2class 2
final test val 2
所以可以看到实际上会执行的过程是这样的:
- 代码执行到class Foo()的时候,Foo的元类会执行,生成类Foo,这时候print语句输出MetaClassTest2class 2
- 代码执行到class FooChild()的时候,FooChild的元类会执行,这时候test为3,print语句输出MetaClassTest3class 3,然后到父类Foo的元类执行,在给test赋值之前已经存在test了,所以print语句输出MetaClassTest2class test in dct 3,然后给test赋值为2,print语句输出为MetaClassTest2class 2,所以最终的test的值为2
从上面来看,子类的__new__的执行和__init__类似,都会先执行子类的,再执行父类的。我们测试一下其它类型的元类定义是否会有这样的现象发生。
class MetaClassTest1class(type):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest1class test in dct', dct['test']
dct['test'] = 1
print dct['test']
return super(MetaClassTest1class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest2class(type):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest2class test in dct', dct['test']
dct['test'] = 2
print 'MetaClassTest2class', dct['test']
return super(MetaClassTest2class, cls).__new__(cls, clsname, bases, dct)
class MetaClassTest3class(MetaClassTest2class):
def __new__(cls, clsname, bases, dct):
if 'test' in dct:
print 'MetaClassTest3class test in dct ', dct['test']
dct['test'] = 3
print 'MetaClassTest3class', dct['test']
return super(MetaClassTest3class, cls).__new__(cls, clsname, bases, dct)
def test_inherite(future_class_name, future_class_parents, future_class_attr):
if 'test' in future_class_attr:
print 'test in future_class_attr ', future_class_attr['test']
future_class_attr['test'] = 4
print future_class_attr['test']
return type(future_class_name, future_class_parents, future_class_attr)
__metaclass__ = MetaClassTest1class
class Foo():
__metaclass__ = test_inherite
pass
class FooChild(Foo):
pass
f = FooChild()
print 'final test val', f.test
print FooChild.__metaclass__
输出为
4
final test val 4
<unbound method FooChild.test_inherite>
这时候可以看到,子类的__metaclass__为test_inherite,是继承了父类的元类的。
Foo = type('Foo', (), {'test': 1})
FooChild = type('FooChild', (Foo,), {'test': 2})
f = Foo()
print f.test
fc = FooChild()
print fc.test
print Foo.__metaclass__
输出为
1
2
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-93-be60cc74b7d9> in <module>()
8 fc = FooChild()
9 print fc.test
---> 10 print Foo.__metaclass__
AttributeError: type object 'Foo' has no attribute '__metaclass__'
可以看到,利用type生成的类,并没有__metaclass__属性。