Python 面試高頻問題:__Init__ 和__New__的區(qū)別
在Python類內部定義,以_ _ xx _ _ 結尾的方法,都是類的內置方法,也稱之為魔法方法。
類的內置方法,會在某種條件滿足下自動觸發(fā),這里我們重點講解一下__init__和__new__,他們與實例創(chuàng)建有關。
簡述__init__
__init__(self): 這個方法我們相對較熟悉,他是python 類中默認的初始化方法,即一個類實例化時,就會執(zhí)行的方法。
詳解__new__
__new__ 方法重寫非常固定,通常如下:
def __new__(cls):
return super().__new__(cls)
其中cls 代表類本身。
重寫__new__方法的代碼非常固定:重寫__new__方法一定要return super().__new__(cls),或者return object.__new__(cls)否則python解釋器會得不到分配了空間的對象引用,就不會調用對象的初始化方法。例如:
class Mycls:
def __new__(cls):
print('new')
return super().__new__(cls)
def __init__(self):
print('init')
my=Mycls()
輸出:
- new
- init
我們可以看到new 在init之前輸出,證明__new__(cls)在__init__(self)之前執(zhí)行。
我們重寫代碼:
def __new__(cls):
print('new')
my=Mycls()
print(my)
輸出:
- new
- None
可以看到如果__new__(cls):中沒有返回值,不會返回實例,__init__(self)將不會執(zhí)行。
__new__和__init__總結
1.__new__()方法用于創(chuàng)建實例,類實例化之前會首先調用,它是class的方法,是個靜態(tài)方法。而__init__()方法用戶初始化實例,該方法用在實例對象創(chuàng)建后被調用,它是實例對象的方法,用于設置類實例對象的一些初始值。
2.如果類中同時出現了__init__()方法和__new__()方法,則先調用__new__()方法后調用__init__()方法。__new__()方法是創(chuàng)建實例的第一步,執(zhí)行完了需要返回創(chuàng)建的類的實例,否則則報錯,無法執(zhí)行__init__()方法。其中,__init__()方法將不返回任何信息。
__new__的應用
有的同學會問 用__new__來實現什么東東呢?
個人覺得,單例就是一個最經典的應用。單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當我們希望在整個系統(tǒng)中,某個類只能出現一個實例時,單例對象就能派上用場。例如,一個系統(tǒng)中可以存在多個打印任務,但是只能有一個正在工作的任務;一個系統(tǒng)只能有一個窗口管理器或文件系統(tǒng);一個系統(tǒng)只能有一個計時工具或ID(序號)生成器。
具體實現代碼如下:
class Mycls:
_instance = None
def __new__(cls):
# 判斷該類的屬性是否為空;對第一個對象沒有被創(chuàng)建,我們應該調用父類的方法,為第一個對象分配空間
if cls._instance == None:
# 把類屬性中保存的對象引用返回給python的解釋器
cls._instance = object.__new__(cls)
return cls._instance
# 如果cls._instance不為None,直接返回已經實例化了的實例對象
else:
return cls._instance
def __init__(self):
print('init')
my1=Mycls()
print(my1)
my2=Mycls()
print(my2)
輸出:
init
<__main__.Mycls object at 0x000000406E471148>
Init
<__main__.Mycls object at 0x000000406E471148>
可以看到雖然叫my1 和my2,但是他們都是對象0x000000406E471148,這就是單例模式的應用。