Python 中的

我們首先得從 __new__(cls[,…]) 的參數說說起,__new__ 方法的第一個參數是這個類,而其餘的參數會在調用成功後全部傳遞給 __init__ 方法初始化,這一下子就看出了誰是老子誰是小子的關係。

所以,__new__ 方法(第一個執行)先於 __init__ 方法執行:

<code>class A:
pass

class B(A):
def __new__(cls):
print("__new__方法被執行")
return super().__new__(cls)
def __init__(self):
print("__init__方法被執行")

b = B()
/<code>

執行結果為:

<code>__new__方法被執行
__init__方法被執行
/<code>

我們比較兩個方法的參數,可以發現 __new__ 方法是傳入類 (cls),而 __init__ 方法傳入類的實例化對象 (self),而有意思的是,__new__ 方法返回的值就是一個實例化對象(ps: 如果 __new__ 方法返回 None,則 __init__ 方法不會被執行,並且返回值只能調用父類中的 __new__ 方法,而不能調用毫無關係的類的 __new__ 方法)。我們可以這麼理解它們之間的關係,__new__ 是開闢疆域的大將軍,而 __init__ 是在這片疆域上辛勤勞作的小老百姓,只有 __new__ 執行完後,開闢好疆域後,__init__ 才能工作,結合到代碼,也就是 __new__ 的返回值正是 __init__ 中 self。

我們可以看下面這個例子:

<code>class CapStr(str):
def __new__(cls, string):
self_in_init = super().__new__(cls, string)
print(id(self_in_init))
return self_in_init
def __init__(self,string):
print(id(self))

a = CapStr("I love China!")
print(id(a))
/<code>

執行結果為:

<code>2691640428616
2691640428616
2691640428616
/<code>

上面這段代碼的內容很簡單,在 __new__ 中打印一下返回值的 id,在 __init__ 中打印一下 self 的 id 值,最後再打印一下創建的這個類的 id 值(所謂的 id 值也就是內存地址),我們可以看到最後的輸出結果是一致的,這也就說明,整個類的地盤是由 __new__ 函數 "開闢出來的",而到了 __init__ 內部就只能在這片地盤上 "修修補補" 了。

小結:__new__ 和 __init__ 相配合才是 python 中真正的類構造器。


分享到:


相關文章: