Python继承中的元类
来源:互联网 发布:连锁超市软件 编辑:程序博客网 时间:2024/05/16 06:51
继承中的元类
首先写代码测试的时候发现问题
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__ = MetaClassTest1classclass Foo(): __metaclass__ = MetaClassTest2class passclass FooChild(Foo): __metaclass__ = MetaClassTest3class passf = 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__ = MetaClassTest1classclass Foo(): __metaclass__ = MetaClassTest2class passclass FooChild(Foo): __metaclass__ = MetaClassTest3class passf = FooChild()print 'final test val', f.test
输出为
MetaClassTest2class 2MetaClassTest3class 3MetaClassTest2class test in dct 3MetaClassTest2class 2final 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__ = MetaClassTest1classclass Foo(): __metaclass__ = test_inherite passclass FooChild(Foo): passf = FooChild()print 'final test val', f.testprint FooChild.__metaclass__
输出为
4final 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.testfc = FooChild()print fc.testprint Foo.__metaclass__
输出为
12---------------------------------------------------------------------------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__属性。
0 0
- Python继承中的元类
- python中的元类
- python中的元类
- Python中的元类
- Python中的元类
- Python中的元类
- Python中的元类
- Python中的元类
- 【python】继承 定制 使用元类
- Python中的元类编程
- Python 中的元类编程
- Python 中的元类编程
- Python中的元类(metaclass)
- Python中的元类(metaclass)
- Python中的元类(metaclass)
- python中的元类Metaclass
- python中的元类Metaclass
- Python中的类和继承
- 无间断大图滚动
- HTML5基础之HTML-表单
- Retrofit框架学习(二)
- GO_BLOCK in WHEN_VALIDATE Trigger
- Technocup 2017 - Elimination Round 1
- Python继承中的元类
- ubuntu15.04怎么把英文界面设置成中文
- tweenjs大图滚动
- 使用C语言进行面向对象的开发--GObject入门[6]
- Linux中的文件描述符与打开文件之间的关系
- python中while循环的注意事项。
- 鼠标移入移出事件
- 基于opencv的单张图像去雾算法(一)
- android自定义ViewGroup之瀑布流FlowLayout 简洁明了 支持padding和margin 100行代码搞定