__new__方法
作用: 用來創(chuàng)建一個類的實例,有返回值,返回當(dāng)前類的一個新的實例.
屬性: 是一個靜態(tài)方法,被請求的類作為第一個參數(shù),返回值值通常是類的新的對象實例.
如果__new__()
返回類的新的實例,則__init__()
方法將會對這個心的實例進(jìn)行初始化.
如果__new__()
沒有返回類的新的實例,那么新的實例的__init__()方法將不會被調(diào)用
# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/6 13:13'
class Person(object):
def __new__(cls, name, age):
print('__new__()方法被調(diào)用')
return super(Person, cls).__new__(cls)
def __init__(self, name, age):
print('__init__()方法被調(diào)用')
self.name = name
self.age = age
def __str__(self):
return '<Person: {}{}>'.format(self.name, self.age)
if __name__ == '__main__':
p = Person('fioman', '24')
print(p)
一些說明:
1鞭缭、繼承自object的新式類才有__new__
2碍粥、__new__
至少要有一個參數(shù)cls渐扮,代表當(dāng)前類合冀,此參數(shù)在實例化時由Python解釋器自動識別
3向楼、__new__
必須要有返回值,返回實例化出來的實例,這點在自己實現(xiàn)__new__
時要特別注意,可以return父類(通過super(當(dāng)前類名, cls))__new__
出來的實例喉酌,或者直接是object的__new__
出來的實例
4热凹、__init__
有一個參數(shù)self泵喘,就是這個__new__
返回的實例,__init__
在__new__
的基礎(chǔ)上可以完成一些其它初始化的動作般妙,init不需要返回值
5纪铺、如果__new__
創(chuàng)建的是當(dāng)前類的實例,會自動調(diào)用__init__
函數(shù)碟渺,通過return語句里面調(diào)用的__new__
函數(shù)的第一個參數(shù)是 cls 來保證是當(dāng)前類實例鲜锚,如果是其他類的類名,苫拍;那么實際創(chuàng)建返回的就是其他類的實例芜繁,其實就不會調(diào)用當(dāng)前類的__init__
函數(shù),也不會調(diào)用其他類的__init__
函數(shù)绒极。
6骏令、在定義子類時沒有重新定義__new__
()時,Python默認(rèn)是調(diào)用該類的直接父類的__new__()
方法來構(gòu)造該類的實例垄提,如果該類的父類也沒有重寫__new__()
榔袋,那么將一直按此規(guī)矩追溯至object的__new__()
方法周拐,因為object是所有新式類的基類。
7凰兑、而如果子類中重寫了__new__()
方法妥粟,那么你可以自由選擇任意一個的其他的新式類(必定要是新式類,只有新式類必定都有__new__()
吏够,因為所有新式類都是object的后代勾给,而經(jīng)典類則沒有__new__()
方法)的__new__()
方法來制造實例,包括這個新式類的所有前代類和后代類稿饰,只要它們不會造成遞歸死循環(huán)锦秒。反正肯定不能調(diào)用自己的__new__
,這肯定是死循環(huán)喉镰。
8旅择、對于子類的__init__
,其調(diào)用規(guī)則跟__new__
是一致的侣姆,當(dāng)然如果子類和父類的__init__
函數(shù)都想調(diào)用生真,可以在子類的__init__
函數(shù)中加入對父類__init__
函數(shù)的調(diào)用。
9捺宗、我們在使用時柱蟀,盡量使用__init__
函數(shù),不要去自定義__new__
函數(shù)蚜厉,因為這兩者在繼承派生時的特性還是很不一樣的长已。
10、將類比作制造商昼牛,__new__
方法就是前期的原材料購買環(huán)節(jié)术瓮,__init__
方法就是在有原材料的基礎(chǔ)上,加工贰健,初始化商品環(huán)節(jié)
__init__
方法
init__()方法在new()方法創(chuàng)建實例后胞四,實例被返回給調(diào)用者之前調(diào)用。它的參數(shù)是傳遞給構(gòu)造表達(dá)式的那些參數(shù)伶椿。如果基類具有init()方法辜伟,那么派生類的init()方法(如果有)必須顯示調(diào)用調(diào)用基類的_init-()方法,如:super().init([args...]).
因為new()方法和init()方法在創(chuàng)建對象時是一起工作的(new()創(chuàng)建對象脊另,init()自定義對象)导狡,而init()方法可能會返回一個非None的值,如果真是這樣偎痛,那么運行時可能會導(dǎo)致TypeError.
區(qū)別:
A. __new__
是一個靜態(tài)方法旱捧,而__init__
是一個實例方法
B. __new__
方法會返回一個創(chuàng)建的實例,而__init__
什么都不返回
C. 只有在__new__
返回一個cls的實例時看彼,后面的__init__
才能被調(diào)用
D. 當(dāng)創(chuàng)建一個新實例時調(diào)用__new__
廊佩,初始化一個實例時用__init__