1. 程式人生 > >深入解析類對象與類實例的創建過程

深入解析類對象與類實例的創建過程

ini 需要 type call 方法 一個 metaclass 補充 bsp


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類的實例。

深入解析類對象與類實例的創建過程