裝飾器翻翩、裝飾器類與類裝飾器(三)

12.類裝飾器是什么(用于裝飾類的裝飾器)

注意與裝飾器類的區(qū)別

  • 裝飾器的原理就是將函數(shù)對象傳入,功能增強后再傳出嫂冻,因此函數(shù)可以被裝飾器裝飾;
  • 同理桨仿,類也可以作為對象被傳入,也可以作為對象被傳出钱雷,所以類也可以被裝飾器裝飾伴嗡。

13.一個類實例的創(chuàng)建過程——__new__

__new__() 是一種負責(zé)創(chuàng)建類實例的靜態(tài)方法,它無需使用 @staticmethod 裝飾器修飾瘪校,且該方法會優(yōu)先 __init__() 初始化方法被調(diào)用名段。
一般情況下泣懊,覆寫 __new__()的實現(xiàn)將會使用合適的參數(shù)調(diào)用其超類的 super().__new__(),并在返回之前修改實例馍刮。例如:
13_newMethodInCls.py

class DemoClass:
    instances_created = 0

    def __new__(cls, *args, **kwargs):
        print("__new__():", cls, args, kwargs)
        instance = super().__new__(cls)
        print('instance:', instance)
        instance.number = cls.instances_created
        cls.instances_created += 1
        return instance

    def __init__(self, attribute):
        print("__init__():", self, attribute)
        self.attribute = attribute


test1 = DemoClass("abc")
print('test1:', test1)
print("\n----------------\n")
test2 = DemoClass("xyz")
print('test2:', test2)
print("\n----------------\n")
print(test1.number, test1.instances_created)
print(test2.number, test2.instances_created)

輸出結(jié)果為:
__new__(): <class '__main__.DemoClass'> ('abc',) {}
instance: <__main__.DemoClass object at 0x00000161CA9F2EB0> 0
__init__(): <__main__.DemoClass object at 0x00000161CA9F2EB0> abc
test1: <__main__.DemoClass object at 0x00000161CA9F2EB0>

----------------

__new__(): <class '__main__.DemoClass'> ('xyz',) {}
instance: <__main__.DemoClass object at 0x00000161CA9F2DF0> 1
__init__(): <__main__.DemoClass object at 0x00000161CA9F2DF0> xyz
test2: <__main__.DemoClass object at 0x00000161CA9F2DF0>

----------------

0 2
1 2
  • Python中存在于類中的構(gòu)造方法__init__()負責(zé)將類實例化卡啰,而在__init__()執(zhí)行之前,__new__()負責(zé)制造這樣的一個實例對象匈辱,以便__init__()去讓該實例對象更加的豐富(為其添加屬性等)。

  • 同時:__new__()方法還決定是否要使用該__init__()方法亡脸,因為__new__()可以調(diào)用其他類的構(gòu)造方法或者直接返回別的對象來作為本類的實例。

如果將類比喻為工廠大州,那么init()方法則是該工廠的生產(chǎn)工人垂谢,init()方法接受的初始化參 數(shù)則是生產(chǎn)所需原料厦画,init()方法會按照方法中的語句負責(zé)將原料加工成實例以供工廠出貨埂陆。而 new()則是生產(chǎn)部經(jīng)理,new()方法可以決定是否將原料提供給該生產(chǎn)部工人购裙,同時它還決定著出 貨產(chǎn)品是否為該生產(chǎn)部的產(chǎn)品,因為這名經(jīng)理可以借該工廠的名義向客戶出售完全不是該工廠的產(chǎn)品躏率。

需要注意的是

  1. 在實例化test1的時候民鼓,“項目經(jīng)理”把自己的cls.instances_createdtest1.instances_created地址弄成一樣的了
  2. 在在實例化test2的時候,“項目經(jīng)理”還是那個項目經(jīng)理丰嘉,把自己的cls.instances_created地址改變賦給test2.instances_created,此時test1.instances_created地址跟著改變耍贾。
    所以最后test1阅爽、test2instances_created屬性值一樣荐开。

用這個原理,就可以將__new__重新覆寫百侧,讓他返回單例

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

14.構(gòu)造類裝飾器——用函數(shù)裝飾器

假設(shè)有很多類赫粥,但是都需要加上一個輸出偶數(shù)的方法,以14_decoratorForClsExample.py其中的一個NumProcessing類為例

def print_evens(self):
    for i in range(self.num):
        if i % 2 == 0:
            print(i)


def decorator(cls):
    print("開始對類進行裝飾")
    cls.print_evens = print_evens
    return cls


@decorator
class NumProcessing:

    num = 1000

    def __init__(self, num):
        print("開始初始化")
        self.num = num

    def print_odds(self):
        for i in range(self.num):
            if i % 2 == 1:
                print(i)


if __name__ == '__main__':
    num_processing = NumProcessing(5)
    num_processing.print_odds()
    num_processing.print_evens()

輸出結(jié)果為;
開始對類進行裝飾
開始初始化
1
3
0
2
4

這個裝飾器的邏輯就是

  1. NumProcessing這個類對象傳入decorator裝飾器中
  2. 然后在裝飾器中新增成員print_evens
  3. 再將輸出偶數(shù)的函數(shù)對象print_odds傳入新增成員print_evens,使其成為方法
  4. 最后將裝飾好的類返回


總結(jié):

用大白話說灵迫,@裝飾器這個語法糖就是把被裝飾的函數(shù)對象作為參數(shù)傳進@后面跟著的東西再加個括號,比如如果是@A挣跋,那么被裝飾的函數(shù)其實就是被包裹進A()里面,如果@A()避咆,那么就是被包裹進A()()里面因為A()返回的才是起裝飾作用的函數(shù)修噪,A()傳進去的是裝飾器的參數(shù),這也是為什么裝飾函數(shù)或者裝飾類需要能調(diào)用的原因黄琼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市围苫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剂府,老刑警劉巖剃盾,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件强法,死亡現(xiàn)場離奇詭異湾笛,居然都是意外死亡饮怯,警方通過查閱死者的電腦和手機嚎研,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來临扮,“玉大人,你說我怎么就攤上這事杆勇。” “怎么了蚜退?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵钻注,是天一觀的道長蚂且。 經(jīng)常有香客問我幅恋,道長,這世上最難降的妖魔是什么捆交? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮玄括,結(jié)果婚禮上诵盼,老公的妹妹穿的比我還像新娘。我一直安慰自己风宁,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布热监。 她就那樣靜靜地躺著,像睡著了一般孝扛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上苦始,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音理郑,去河邊找鬼。 笑死您炉,一個胖子當(dāng)著我的面吹牛役电,可吹牛的內(nèi)容都是我干的赚爵。 我是一名探鬼主播法瑟,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畸写!你這毒婦竟也來了氓扛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤采郎,失蹤者是張志新(化名)和其女友劉穎狂魔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體最楷,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年烈评,在試婚紗的時候發(fā)現(xiàn)自己被綠了犯建。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡适瓦,死狀恐怖谱仪,靈堂內(nèi)的尸體忽然破棺而出否彩,到底是詐尸還是另有隱情,我是刑警寧澤列荔,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肌毅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏悬而。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一袭蝗、第九天 我趴在偏房一處隱蔽的房頂上張望般婆。 院中可真熱鬧到腥,春花似錦蔚袍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓶佳。三九已至鳞青,卻和暖如春霸饲,著一層夾襖步出監(jiān)牢的瞬間臂拓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工埃儿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓威鹿,卻偏偏與公主長得像轨香,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子臂容,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

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