Python完善decorator

來源:互聯網
上載者:User

標籤:lambda   python   performance   

@decorator可以動態實現函數功能的增加,但是,經過@decorator“改造”後的函數,和原函數相比,除了功能多一點外,有沒有其它不同的地方?

在沒有decorator的情況下,列印函數名:

def f1(x):    passprint f1.__name__

輸出: f1

有decorator的情況下,再列印函數名:

def log(f):    def wrapper(*args, **kw):        print ‘call...‘        return f(*args, **kw)    return wrapper@logdef f2(x):    passprint f2.__name__

輸出: wrapper

可見,由於decorator返回的新函數函數名已經不是‘f2‘,而是@log內部定義的‘wrapper‘。這對於那些依賴函數名的代碼就會失效。decorator還改變了函數的__doc__等其它屬性。如果要讓調用者看不出一個函數經過了@decorator的“改造”,就需要把原函數的一些屬性複製到新函數中:

def log(f):    def wrapper(*args, **kw):        print ‘call...‘        return f(*args, **kw)    wrapper.__name__ = f.__name__    wrapper.__doc__ = f.__doc__    return wrapper

這樣寫decorator很不方便,因為我們也很難把原函數的所有必要屬性都一個一個複製到新函數上,所以Python內建的functools可以用來自動化完成這個“複製”的任務:

import functoolsdef log(f):    @functools.wraps(f)    def wrapper(*args, **kw):        print ‘call...‘        return f(*args, **kw)    return wrapper

最後需要指出,由於我們把原函數簽名改成了(*args, **kw),因此,無法獲得原函數的原始參數資訊。即便我們採用固定參數來裝飾只有一個參數的函數:

def log(f):    @functools.wraps(f)    def wrapper(x):        print ‘call...‘        return f(x)    return wrapper

也可能改變原函數的參數名,因為新函數的參數名始終是 ‘x‘,原函數定義的參數名不一定叫 ‘x‘。

任務

請思考帶參數的@decorator,@functools.wraps應該放置在哪:

def performance(unit):    def perf_decorator(f):        def wrapper(*args, **kw):            ???        return wrapper    return perf_decorator
?不會了怎麼辦

注意@functools.wraps應該作用在返回的新函數上。

參考代碼:

import time, functoolsdef performance(unit):    def perf_decorator(f):        @functools.wraps(f)        def wrapper(*args, **kw):            t1 = time.time()            r = f(*args, **kw)            t2 = time.time()            t = (t2 - t1) * 1000 if unit==‘ms‘ else (t2 - t1)            print ‘call %s() in %f %s‘ % (f.__name__, t, unit)            return r        return wrapper    return perf_decorator@performance(‘ms‘)def factorial(n):    return reduce(lambda x,y: x*y, range(1, n+1))print factorial.__name__

Python完善decorator

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.