詳解Python中的__init__和__new__

原文出處: for-in

一畴博、__init__ 方法是什么俱病?

使用Python寫過面向?qū)ο蟮拇a的同學亮隙,可能對 init 方法已經(jīng)非常熟悉了溢吻,init 方法通常用在初始化一個類實例的時候促王。例如:

# -*- coding: utf-8 -*-
 
class Person(object):
    """Silly Person"""
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)
 
if __name__ == '__main__':
    piglei = Person('piglei', 24)
    print piglei

這樣便是__init__最普通的用法了蝇狼。但__init__其實不是實例化一個類的時候第一個被調(diào)用 的方法题翰。當使用 Persion(name, age) 這樣的表達式來實例化一個類時,最先被調(diào)用的方法 其實是 __new__方法冯事。

二昵仅、new 方法是什么?

__new__方法接受的參數(shù)雖然也是和__init__一樣累魔,但__init__是在類實例創(chuàng)建之后調(diào)用摔笤,而 __new__方法正是創(chuàng)建這個類實例的方法。

# -*- coding: utf-8 -*-
 
class Person(object):
    """Silly Person"""
 
    def __new__(cls, name, age):
        print '__new__ called.'
        return super(Person, cls).__new__(cls, name, age)
 
    def __init__(self, name, age):
        print '__init__ called.'
        self.name = name
        self.age = age
 
    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)
 
if __name__ == '__main__':
    piglei = Person('piglei', 24)
    print piglei

執(zhí)行結(jié)果:

piglei@macbook-pro:blog$ python new_and_init.py
__new__ called.
__init__ called.
<Person: piglei(24)>

通過運行這段代碼垦写,我們可以看到吕世,__new__方法的調(diào)用是發(fā)生在__init__之前的。其實當 你實例化一個類的時候梯投,具體的執(zhí)行邏輯是這樣的:

1.p = Person(name, age)
2.首先執(zhí)行使用name和age參數(shù)來執(zhí)行Person類的__new__方法命辖,這個__new__方法會 返回Person類的一個實例(通常情況下是使用 super(Persion, cls).__new__(cls, … …) 這樣的方式),
3.然后利用這個實例來調(diào)用類的init方法分蓖,上一步里面new產(chǎn)生的實例也就是 __init__里面的的 self
所以尔艇,__init____new__ 最主要的區(qū)別在于:
1.__init__通常用于初始化一個新實例,控制這個初始化的過程么鹤,比如添加一些屬性终娃, 做一些額外的操作迅皇,發(fā)生在類實例被創(chuàng)建完以后。它是實例級別的方法。
2.__new__通常用于控制生成一個新實例的過程喇嘱。它是類級別的方法。
但是說了這么多愉粤,__new__最通常的用法是什么呢影暴,我們什么時候需要__new__伦吠?

三箭跳、__new__ 的作用

依照Python官方文檔的說法刨晴,new方法主要是當你繼承一些不可變的class時(比如int, str, tuple)蝶桶, 提供給你一個自定義這些類的實例化過程的途徑脐雪。還有就是實現(xiàn)自定義的metaclass脂信。
首先我們來看一下第一個功能梢薪,具體我們可以用int來作為一個例子:
假如我們需要一個永遠都是正數(shù)的整數(shù)類型,通過集成int,我們可能會寫出這樣的代碼歧胁。

class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))
 
i = PositiveInteger(-3)
print i

但運行后會發(fā)現(xiàn)崭参,結(jié)果根本不是我們想的那樣,我們?nèi)稳坏玫搅?3跨新。這是因為對于int這種 不可變的對象,我們只有重載它的__new__方法才能起到自定義的作用。
這是修改后的代碼:

class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))
 
i = PositiveInteger(-3)
print i

通過重載new方法陋率,我們實現(xiàn)了需要的功能菩浙。
另外一個作用,關(guān)于自定義metaclass。其實我最早接觸new的時候酥筝,就是因為需要自定義 metaclass阅束,但鑒于篇幅原因呼盆,我們下次再來講python中的metaclass和new的關(guān)系况脆。

四盛末、用__new__來實現(xiàn)單例

事實上,當我們理解了__new__方法后侠讯,我們還可以利用它來做一些其他有趣的事情宵膨,比如實現(xiàn) 設(shè)計模式中的 單例模式(singleton) 。
因為類每一次實例化后產(chǎn)生的過程都是通過__new__來控制的瑞凑,所以通過重載__new__方法,我們 可以很簡單的實現(xiàn)單例模式篱蝇。

class Singleton(object):
    def __new__(cls):
        # 關(guān)鍵在于這涧衙,每一次實例化的時候弧哎,我們都只會返回這同一個instance對象
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance
 
obj1 = Singleton()
obj2 = Singleton()
 
obj1.attr1 = 'value1'
print obj1.attr1, obj2.attr1
print obj1 is obj2

輸出結(jié)果:

value1 value1
True

可以看到obj1和obj2是同一個實例序攘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慌核,一起剝皮案震驚了整個濱河市钾怔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舶斧,老刑警劉巖欣鳖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茴厉,居然都是意外死亡泽台,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門矾缓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怀酷,“玉大人,你說我怎么就攤上這事嗜闻⊥梢溃” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵琉雳,是天一觀的道長样眠。 經(jīng)常有香客問我,道長咐吼,這世上最難降的妖魔是什么吹缔? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮锯茄,結(jié)果婚禮上厢塘,老公的妹妹穿的比我還像新娘。我一直安慰自己肌幽,他們只是感情好晚碾,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喂急,像睡著了一般格嘁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上廊移,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天糕簿,我揣著相機與錄音,去河邊找鬼狡孔。 笑死懂诗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的苗膝。 我是一名探鬼主播殃恒,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了离唐?” 一聲冷哼從身側(cè)響起病附,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亥鬓,沒想到半個月后完沪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡贮竟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年丽焊,在試婚紗的時候發(fā)現(xiàn)自己被綠了较剃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咕别。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖写穴,靈堂內(nèi)的尸體忽然破棺而出惰拱,到底是詐尸還是另有隱情,我是刑警寧澤啊送,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布偿短,位于F島的核電站,受9級特大地震影響馋没,放射性物質(zhì)發(fā)生泄漏昔逗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一篷朵、第九天 我趴在偏房一處隱蔽的房頂上張望勾怒。 院中可真熱鬧,春花似錦声旺、人聲如沸笔链。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鉴扫。三九已至,卻和暖如春澈缺,著一層夾襖步出監(jiān)牢的瞬間坪创,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工姐赡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留莱预,地道東北人。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓雏吭,卻偏偏與公主長得像锁施,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Class也是Object 在理解metaclass之前悉抵,我們需要先理解Python中的class肩狂。從某種程度上來...
    耀凱考前突擊大師閱讀 25,852評論 6 34
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)姥饰,斷路器傻谁,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法列粪,內(nèi)部類的語法审磁,繼承相關(guān)的語法,異常的語法岂座,線程的語...
    子非魚_t_閱讀 31,624評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,083評論 25 707
  • 探尋睡眠與夢态蒂,夢與現(xiàn)實的關(guān)聯(lián)很久了》咽玻總覺得夢是思維主導下的產(chǎn)物钾恢,是有傾向性的。所想所思所感所觸都影響著夢鸳址。
    樸素少年_大美閱讀 126評論 0 0