摘要:本文旨在澄清里和的概念。的創(chuàng)建并返回的這個(gè)實(shí)例,是裸的。然后我們的的再接手這個(gè)裸的實(shí)例去進(jìn)一步加工,比如加上各種,或再執(zhí)行一些別的這個(gè)過(guò)程就是。如果用了,那么就可以無(wú)視這個(gè),因?yàn)榫涂梢岳斫獬梢粋€(gè)普通的函數(shù)表示這個(gè)類本身。
本文旨在澄清 python 里 __new__ vs __init__ 和 cls vs self 的概念。
很多初學(xué)者會(huì)困擾,python的“魔法函數(shù)” __new__ 有啥用? 跟__init__有啥區(qū)別? 為什么有的函數(shù)第一個(gè)輸入變量是self, 有的卻是cls? 這有啥區(qū)別?
好,廢話不多說(shuō),先看一個(gè)例子:
class A(object): def __new__(cls): print("A.__new__ called") return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A() print("finished")
運(yùn)行結(jié)果為:
A.__new__ called A.__init__ called finished
為什么結(jié)果是這樣呢?
因?yàn)椋?b>__new__ 負(fù)責(zé)創(chuàng)建一個(gè) object;之后 __init__ 負(fù)責(zé)初始化這個(gè) object。
有點(diǎn)繞是吧,再說(shuō)具體點(diǎn):
當(dāng)A()被 call 的時(shí)候,__new__ 就自動(dòng)執(zhí)行了, 它創(chuàng)建了一個(gè)object(class的具體實(shí)例)并返回這個(gè)object,然后__init__接手這個(gè)實(shí)例再接著執(zhí)行。
每當(dāng)__new__ 創(chuàng)建并返回一個(gè)實(shí)例時(shí),__init__ 就接手這個(gè)實(shí)例然后執(zhí)行,這個(gè)實(shí)例就是__init__ 的第一個(gè)輸入變量,永遠(yuǎn)不變的, 默認(rèn)的self。 說(shuō)到這里,self怎么來(lái)的應(yīng)該很清楚了吧。
在平常應(yīng)用中,我們定義某個(gè)class時(shí)幾乎不會(huì)去寫它的__new__方法,于是當(dāng)我們call這個(gè)class時(shí),python會(huì)一直往上追溯到有__new__的父輩class, 通常我們自定義的class都是object的子類,所以執(zhí)行的都是它的__new__。
object的__new__創(chuàng)建并返回的這個(gè)實(shí)例,是裸的。 然后我們的class的__init__再接手這個(gè)裸的實(shí)例去進(jìn)一步加工,比如加上各種 self.xxx = xxx, 或再執(zhí)行一些別的code, 這個(gè)過(guò)程就是initialization。注意它和creation的區(qū)別,應(yīng)該說(shuō)的很清晰了吧。
那假如我們自己定義一個(gè)壞了的__new__, 它沒(méi)有返回一個(gè)實(shí)例,這事會(huì)發(fā)生什么呢?比如:
class A(object): def __new__(cls): print("A.__new__ called") #return super(A, cls).__new__(cls) def __init__(self): print("A.__init__ called") A()
運(yùn)行一下,發(fā)現(xiàn)結(jié)果是:
A.__new__ called finished
哈哈當(dāng)然啦,__new__沒(méi)有返回一個(gè)創(chuàng)建好的實(shí)例,那么__init__自然就執(zhí)行不了了。 上頭沒(méi)有提供食材,廚子就揭不開鍋?zhàn)鲲埪铩?
這個(gè)時(shí)候有人會(huì)問(wèn)了,為啥 __init__() 里面是 self, 而__new__()里面是cls呢?
首先,我們澄清一下概念:
1、self表示一個(gè)具體的實(shí)例(instance)本身。(如果用了@staticmethod,那么就可以無(wú)視這個(gè)self,因?yàn)閟taticmethod就可以理解成一個(gè)普通的函數(shù))
2、cls表示這個(gè)類(class)本身。
OK, __init__() 里面的self已經(jīng)說(shuō)清楚了,是剛剛__new__出爐的一個(gè)創(chuàng)建好的實(shí)例(object / instance); 那__new__()里面是cls又是指哪個(gè)class呢?
簡(jiǎn)單說(shuō)來(lái):哪個(gè)class召喚了__new__, cls就默認(rèn)是哪個(gè)class。
再看一個(gè)例子 (Singleton 單例模式的實(shí)現(xiàn)):
class Singleton(object): def __new__(cls, *args, **kw): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) print(" ") print("cls is ", cls) print(type(cls._instance), cls._instance) else: print(" {} already exists".format(cls._instance)) return cls._instance class Bus(Singleton): def sendData(self,data): pass class BusSon(Bus): def sendData(self,data): pass if __name__ == "__main__": busson1 = BusSon() bus1 = Bus() print("------------------------ ") busson2 = BusSon() bus2 = Bus() print("------------------------ ") Bus.__new__(BusSon) Bus() x = Singleton.__new__(Bus) print(x)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/43944.html
摘要:本篇文章總結(jié)了目前主流的實(shí)現(xiàn)單例模式的方法供讀者參考。使用實(shí)現(xiàn)單例模式同樣,我們?cè)陬惖膭?chuàng)建時(shí)進(jìn)行干預(yù),從而達(dá)到實(shí)現(xiàn)單例的目的。 很多初學(xué)者喜歡用 全局變量 ,因?yàn)檫@比函數(shù)的參數(shù)傳來(lái)傳去更容易讓人理解。確實(shí)在很多場(chǎng)景下用全局變量很方便。不過(guò)如果代碼規(guī)模增大,并且有多個(gè)文件的時(shí)候,全局變量就會(huì)變得比較混亂。你可能不知道在哪個(gè)文件中定義了相同類型甚至重名的全局變量,也不知道這個(gè)變量在程序的某...
摘要:南京現(xiàn)在算是我的一個(gè)治愈城市了,帶著重重的悲傷去,幸好落雪的瞬間將我治愈。年,世界和平,平安喜樂(lè)。繼承與多態(tài)繼承就是從現(xiàn)有的類進(jìn)行繼承,被繼承的為超類或者父類也就是爸爸,新的類為子類。 叨叨點(diǎn)啥 2018年的最后一天?;仡欉@一年,獲得很多也失去很多。今年去了很多的地方,成都,重慶,峨眉山,天津,杭州,南京。杭州是我特別喜歡的城市,有很多美好的記憶,也有很多失落的時(shí)刻。南京現(xiàn)在算是我的一...
摘要:最前面那個(gè),解釋器實(shí)際的流程是解析這段代碼,得知它需要?jiǎng)?chuàng)建一個(gè)類對(duì)象,這個(gè)類的名字叫做它的父類列表用表示是,它的屬性用一個(gè)來(lái)表示就是。解決方法很簡(jiǎn)單關(guān)鍵就是前面被特別標(biāo)記了的應(yīng)當(dāng)返回這個(gè)的父類的方法返回的對(duì)象。 (原發(fā)于我的blog:Python: metaclass小記 ) 友情提示:本文不一定適合閱讀,如果執(zhí)意要讀,請(qǐng)備好暈車藥。 題記 Metaclasses are deepe...
摘要:它首先被程序語(yǔ)言的設(shè)計(jì)領(lǐng)域所采用并在和面向?qū)ο蠓矫嫒〉昧顺煽?jī)。面向?qū)ο笾械姆瓷渫ㄟ^(guò)字符串的形式操作對(duì)象相關(guān)的屬性。注構(gòu)造方法的執(zhí)行是由創(chuàng)建對(duì)象觸發(fā)的,即對(duì)象類名而對(duì)于方法的執(zhí)行是由對(duì)象后加括號(hào)觸發(fā)的,即對(duì)象或者類執(zhí)行執(zhí)行邏輯題 isinstance和issubclass 1.isinstance(obj,cls)檢查是否obj是否是類 cls 的對(duì)象 #!/usr/bin/env py...
摘要:最近在學(xué)習(xí)設(shè)計(jì)模式而開發(fā)的語(yǔ)言中比較中意的就是了在這里總結(jié)下設(shè)計(jì)模式一般分為三大類構(gòu)造型結(jié)構(gòu)型行為型先從創(chuàng)建型設(shè)計(jì)模式開始創(chuàng)建型設(shè)計(jì)模式包括單例模式抽象工廠模式工廠方法模式生成器模式惰性初始化模式對(duì)象池模式原型模式單例模式單例模式的定義是保 最近在學(xué)習(xí)設(shè)計(jì)模式,而開發(fā)的語(yǔ)言中比較中意的就是python了,在這里總結(jié)下. 設(shè)計(jì)模式一般分為三大類:構(gòu)造型,結(jié)構(gòu)型,行為型 先從創(chuàng)建型設(shè)計(jì)模式...
閱讀 2070·2021-08-11 11:13
閱讀 1099·2021-07-25 21:37
閱讀 2633·2019-08-29 18:42
閱讀 2576·2019-08-26 12:18
閱讀 977·2019-08-26 11:29
閱讀 1753·2019-08-23 17:17
閱讀 2713·2019-08-23 15:55
閱讀 2669·2019-08-23 14:34