Python裝飾器樣本流量分析

來源:互聯網
上載者:User

Python裝飾器樣本流量分析
概述

裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的傳回值也是一個函數對象。

我們要需要一個能測試函數已耗用時間的decorator,可以定義如下:

def timer(func):    def wrapper(*args, **kwargs):        start_time = time.time()        res = func(*args, **kwargs)        end_time = time.time()        print("Run time is: %s" % (end_time - start_time))        return res    return wrapper

因為它是一個decorator,所以接受一個函數作為參數,並返回一個函數。我們要藉助Python的@文法,把decorator置於函數的定義處:

@timerdef fun():    time.sleep(1)    print("This is a test")    return "OK"

運行結果就是:

This is a testRun time is: 1.0000572204589844OK

把@timer放在fun()處就相當於執行了語句:

fun = timer(fun)

如果decorator本身需要傳入參數,那就需要編寫一個返回decorator的高階函數,比如加上名字:

def timer(name):    def decorator(func):        def wrapper(*args, **kwargs):            start_time = time.time()            res = func(*args, **kwargs)            end_time = time.time()            print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))            return res        return wrapper    return decorator

調用及結果顯示如下:

@timer("Lance#")def fun():    time.sleep(1)    print("This is a test")    return "OK"
This is a testName is: Lance# ; Run time is: 1.0000572204589844OK

和兩層嵌套的decorator相比,三層嵌套的效果是這樣的:

fun = timer("Lance#")(fun)

因為函數也是對象,它也有__name__等屬性。
在未加裝飾器之前的fun()函數,調用 fun的__name__屬性結果是 'fun',但經過decorator裝飾之後的函數,它們的__name__已經從原來的'fun'變成了'wrapper'

所以,需要把原始函數的__name__等屬性複製到wrapper()函數中,否則,有些依賴函數簽名的代碼執行就會出錯。

Python內建的functools.wraps就可以完成這個任務,所以,一個完整的decorator的寫法如下:

import functoolsdef timer(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        start_time = time.time()        res = func(*args, **kwargs)        end_time = time.time()        print("Run time is: %s" % (end_time - start_time))        return res    return wrapper

整體代碼如下:

__Author__ = "Lance#"# -*- coding = utf-8 -*-import timeimport functoolsdef timer(name):    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            start_time = time.time()            res = func(*args, **kwargs)            end_time = time.time()            print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))            return res        return wrapper    return decorator@timer("Lance#")def fun():    time.sleep(1)    print("This is a test")    return "OK"if __name__ == '__main__':    print(fun())

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.