都说python很容易,可我咋看的这么难,又是装饰器又是MetaClass的。搞得头大,那么什么是MetaClass,首先,我们要搞清楚python中有两中关系,issubclass和isinstance。issubclass用于判断一个类是否是一个类的父类。isinstance用于判断一个对象是否是一个类的实例。
    MetaClass最基本的类就是type。可以用它来创建一个新的类A,此时这个新的类A就是type的一个实例isinstance(A,type)为真。因此,MetaClass主要用来创建类,并可以对新的类进行修改。我们对下面的代码进行一个解析。
class MyMeta(type):
    def __new__(cls, *args, **kwargs):
        print(1)
        print(cls)
        print('===>MyMeta.__new__')
        print(cls.__name__)
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, classname, superclasses, attributedict):
        super().__init__(classname, superclasses, attributedict)
        print(self)
        print('===>MyMeta.__init__')
        print(self.__name__)
        print(classname)
        print(superclasses)
        print(attributedict)
        print(self.tag)
        print(2)
    def __call__(self, *args, **kwargs):
        print('===>MyMeta.__call__')
        print(self)
        obj = self.__new__(self, *args, **kwargs)
        self.__init__(self, *args, **kwargs)
        print(3)
        return obj


class Foo(object, metaclass=MyMeta):
    tag = '!Foo'
    print(5)
    def __new__(cls, *args, **kwargs):
        print('===>Foo.__new__')
        print(6)
        print(cls)
        return super().__new__(cls)

    def __init__(self, name):
        print(self)
        print('===>Foo.__init__')
        self.name = name
        print(7)


print('test start')
foo = Foo('test')
print('test end')

结果为

5
1
<class '__main__.MyMeta'>
===>MyMeta.__new__
MyMeta
<class '__main__.Foo'>
===>MyMeta.__init__
Foo
Foo
(<class 'object'>,)
{'__module__': '__main__', '__qualname__': 'Foo', 'tag': '!Foo', '__new__': <function Foo.__new__ at 0x000001AF0F1D6B80>, '__init__': <function Foo.__init__ at 0x000001AF0F1D6A60>, '__classcell__': <cell at 0x000001AF0F1D8CA0: MyMeta object at 0x000001AF0EADAAF0>}
!Foo
2
test start
===>MyMeta.__call__
<class '__main__.Foo'>
===>Foo.__new__
6
<class '__main__.Foo'>
<class '__main__.Foo'>
===>Foo.__init__
7
3
test end

首先内存先加载MyMeta,加载__new__,init,__call__方法。然后继续加载Foo类,此时会首先输出5。然后metaclass=MyMeta告诉编译器,Foo类的MetaClass是MyMeta,因为Foo是MyMeta的一个实例,在创建实例时,会首先调用__new__方法,此时输出1,cls就是MyMeta类,args里是Foo类的信息。然后调用__init__方法,self就是Foo,classname为Foo的类名,superclasses为Foo的父类元组,attributedict为Foo类的属性信息字典。然后输出2.接着运行test start,创建Foo的实例,而Foo是MyMeta的实例,因此Foo()会调用MyMeta的__call__方法,此时self为Foo这个实例,则在__call__方法中又会调用Foo的__new__方法先输出6,然后调用Foo的__init__方法输出7.最后输出3.最后输出test end.
由次可见,对于Foo方法,可在MyMeta中的__init__中的attributedict修改Foo的属性,当然,__new__方法也可以。综上,MetaClass就是一个用来创建类的类,与创建的类属于isinstance的关系。


版权声明:本文为weixin_42834523原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_42834523/article/details/121425189