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

所以可以看到实际上会执行的过程是这样的:

  1. 代码执行到class Foo()的时候,Foo的元类会执行,生成类Foo,这时候print语句输出MetaClassTest2class 2
  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
原创粉丝点击