Python中创建对象的内部流程、metaclass和type类
obj = Foo()的执行流程
第一阶段:编译器执行到class Foo(object)时:
1. class Foo 执行,由于metaclass=MyType,所以先执行MyType的__init__方法
2. 这时,obj是一个Foo类的对象,Foo类本身又是MyType类的对象(如果不指定metaclass=MyType,则默认metaclass是系统内置的Type类)
3. MyType的__init__方法调用父类type类的init方法,第一阶段结束
第二阶段:编译器执行到obj = Foo() 时:
4. Foo是一个类,python中一切皆对象,Foo可以看成是MyType类的一个对象,因此,Foo()可以看成以对象名调用了MyType类的__call__方法,所以接下来执行MyType类的__call__方法
5. MyType类的__call__方法调用Foo类(这里就是self)的__new__方法,以及__init__方法
6. 真正创建对象是Foo中的__new__方法调用的object.__new__
7. 这里的self指代Foo,然后执行self.__init__
原文:https://blog.****.net/m0_37519490/article/details/80825934
一、metaclass干嘛的?
metaclass是指定类由谁创建。能够定制类的创建过程
指定类由谁创建的???开什么玩笑,类不是由'我'创建的吗????
python中一切皆对象,类也是对象,类是由type类创建。
我们写下如下代码时:
class Foo(object): pass
实际上,解释器将其解释为:
Foo = type('Foo', (object,), {})
type()的三个参数:'Foo':类名; (object, ): 类的继承关系,用元组表示; {}: 类的字段,方法。
以上是类的默认创建方法。由type创建。python也给我们提供了自定义类的创建的方法,即metaclass。type也是类,它可以创建类,因此我们叫它元类,不要过分纠结这是什么鬼,知道type类可以创建类就行。
自定义类的创建过程,那就得写一个像type一样可以创建类的类,那简单,继承就可以办到。
方式一:
class MyType(type): def __new__(cls, *args, **kwargs): print('MyType __new__') return super().__new__(cls, *args, **kwargs) def __init__(cls, *args, **kwargs): print('MyTpye __init__') super().__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): print('MyTpye __call__') super().__call__(cls, *args, **kwargs) class Foo(metaclass=MyType): pass
这样,解释器解释到class Foo(...)的时候,就会转换为:
Foo = MyType('Foo', (object,), {})
方式二:
class MyType(type): def __new__(cls, *args, **kwargs): print('MyType __new__') return super().__new__(cls, *args, **kwargs) def __init__(cls, *args, **kwargs): print('MyTpye __init__') super().__init__(*args, **kwargs) def __call__(cls, *args, **kwargs): print('MyTpye __call__') super().__call__(cls, *args, **kwargs) def with_meta(meta, Base): return meta('Foo', (Base, ), {}) class Foo(with_meta(MyType, object)): pass
这样解释的时候,与方式一的一样。
二、创建类与类实例化时执行过程是怎样的?
解释器解释到class的定义语句时,会先在class中寻找是否指定自定义的'MyType', 没有再往父类找是否指定,没有再在本模块中找,是否本模块指定了统一的'MyType', 若均没有,则用默认的type创建。
解释到class Foo(...)时,会调用'MyType'的__new__, __init__方法。生成类。
解释到f = Foo() ,类的实例化时,会调用'MyType'的__call__方法,而'type'的__call__方法又会去调用Foo的__new__, __init__实例化类对象。