深入解析类对象与类实例的创建过程


class MyType(type):
def __init__(self,*args,**kwargs):
print("init")
super(MyType, self).__init__(*args,**kwargs)

def __new__(cls, *args, **kwargs):
print("new")
print("mro",cls.__mro__)
# 调用父类的__new__ 方法来实例出一个Base类对象
return super(MyType, cls).__new__(cls, *args, **kwargs)

def __call__(self, *args, **kwargs):
# self = Base类对象
# 调用object类的__new__方法,创建Base的实例对象
obj = object.__new__(self)
# 执行 构造方法
obj.__init__()
print('obj',obj)
return obj


class Base(metaclass=MyType):
def __init__(self):
print("Base init")

def __new__(cls, *args, **kwargs):
ret = super(Base, cls).__new__(cls, *args, **kwargs)
print("Base ret",ret)
return ret

a = Base()
print(a,'a的返回值')

  Base是一个对象,Base()则调用创建该类的__call__方法。执行__call__方法本质上是首先执行Base类中的__new__方法,然后再执行__init__方法,最终将生成的经过初始化的实例对象返回给a。也就是说,__call__方法的返回值是什么,生成的实例对象就是什么。需要注意的是,在__call__方法中,self指的是Base对象,因此 obj = object.__new__(self) 生成的是Base类的对象, obj.__init__() 执行的是Base的__init__方法,至此完成了创建Base类实例的过程。

  需要说明的是,我在元类的__call__方法中以手动的方式执行 __new__和__init__,但也可以用  super(MyType, self).__call__(*args, **kwargs) 完成相同的效果,这里只是为了说明   super(MyType, self).__call__(*args, **kwargs) 的内部执行流程。

super补充

  首先要明确的是,super是一个类,不是一个函数。以 super(MyType, self).__call__(*args, **kwargs) 为例,super(cls,ins)获得是cls在ins的mor表中的下一个类对象,再通过该对象调用该对象下的__call__方法,如果此类中没有__call__方法,那么再按照ins的mro表继续向下查找,无论如何,一定可以在object类中找到__call__方法,在__call__方法中首先创建一个cls的实例,然后执行该实例的__init__方法,从而完成cls类的实例。

 
posted on 2018-09-30 10:33  云烟||成雨  阅读(139)  评论(0编辑  收藏  举报