官术网_书友最值得收藏!

1.2.3 裝飾器

對初學者來說,深入理解裝飾器是比較困難的,這和大家對Python語言的熟悉程度也有一定的關系。這里初步介紹裝飾器的使用。正像其名字一樣,裝飾器是用來“裝飾”的,這里的“裝飾”可以理解為“加強”的意思。也就是說,可以通過裝飾器來加強我們的程序。裝飾器一般用于裝飾函數和類,這里僅介紹對函數的裝飾。

可能有的讀者會想,既然我們想要函數有加強的功能,直接寫在函數里面不就行了?當然可以,這確實是一種可行的方法。但是假設想要每個函數打印此函數執行的時間,按照上面的方法,就要在每個函數里面記錄開始時間和結束時間,然后計算時間差,再打印出此時間差。這樣會使函數變得臃腫,包含太多和函數功能不相關的內容。假設有幾十個這樣的函數將要多出幾十甚至上百行代碼來實現這個功能。所以按照常規的方法,把函數“升級”到加強版是十分煩瑣的。而裝飾器就是化繁為簡的法寶。通過裝飾器,可以通過簡單地定義一個函數,然后在每個函數前多加一行代碼就可以實現函數的“升級”,這就是“裝飾”。這也是使用裝飾器的原因。

先看一個使用裝飾器的例子,如下所示。

    import time

    def printtime(func):
        def wrapper(*args, **kwargs):
          print(time.ctime())
          return func(*args, **kwargs)

        return wrapper

    @printtime
    def printhello(name):
        print('Hello', name)

    if __name__ == '__main__':
        printhello('Sam')

運行輸出如下。

    Wed Jun 28 01:13:042017
    Hello Sam

這里定義了一個裝飾器,用于打印函數開始執行的時間。上面的程序@printtime就是裝飾器的關鍵。下面去掉這句,看看怎樣實現同樣的功能。在這之前,我們必須知道在Python里面,函數也是對象,也能被當作參數傳遞,而裝飾器的本質就是函數。

    import time

    def printtime(func):
        def wrapper(*args, **kwargs):
          print(time.ctime())
          return func(*args, **kwargs)

        return wrapper

    def printhello(name):
        print('Hello', name)

    if __name__ == '__main__':
        printhello_plus = printtime(printhello)
        printhello_plus('Sam')

其輸出同樣可以打印時間和問候語。先看以下兩句代碼。

    printhello_plus = printtime(printhello)
    printhello_plus('Sam')

修改后的代碼將printhello函數作為對象傳給printtime作為參數,然后printtime函數將返回的wrapper函數賦給了printhello_plus,也就是說此時的printhello_plus函數和wrapper函數是一致的。接下來執行printhello_plus函數,就像wrapper函數中寫到的一樣,先打印日期時間,再執行一開始傳入的函數(此處是printhello)。

也就是說,printhello_plus = printtime(printhello)是對原printhello函數進行“加強”的操作。后面的printhello_plus('Sam')是對加強后函數的調用操作。而@printtime實現的正是這個功能,只是少了這個顯式的“加強”并額外賦值的操作。將@printtime置于函數定義之前,就相當于自動進行了“加強”的操作,并且加強版本的函數名還是原來的函數名。

通過這樣的拆解,現在對裝飾器有了基本認識,但是進一步的學習還需要對閉包等概念有更加深入的認識。在后面爬蟲多線程的測試實驗中還會用到,與這里的例子是類似的,讀者可以嘗試著理解。

主站蜘蛛池模板: 阿拉善右旗| 收藏| 怀柔区| 阳城县| 安塞县| 宁蒗| 商水县| 江北区| 乃东县| 格尔木市| 香格里拉县| 车险| 洪泽县| 荔波县| 株洲市| 陈巴尔虎旗| 新田县| 化州市| 景洪市| 阿鲁科尔沁旗| 高邑县| 千阳县| 肥西县| 齐河县| 白河县| 宣武区| 禄劝| 攀枝花市| 兰溪市| 潢川县| 即墨市| 南涧| 荥阳市| 衡山县| 舟曲县| 敦化市| 吉木乃县| 皮山县| 雷波县| 衡东县| 高陵县|