Python裝飾器

此篇緊接上篇 Python裝飾器vs裝飾器模式,上篇主要是簡述了裝飾器模式,跟Python的裝飾器。python

再來看Python裝飾器的實現。這裏我推薦一篇文章(譯)-12步輕鬆搞定python裝飾器,文章寫得很是不錯,看完後對做用於,閉包都感覺很是深,可是我以爲漏了一些點點,我把個人想法闡述在本文算法

補全

根據Java實現裝飾器模式的,咱們能夠寫下面一段代碼:segmentfault

import logging


def use_logging(func):
    logging.warn("%s is running" % func.__name__)
    return func

def foo():
    print('i am foo')

foo = use_logging(foo)

foo() # 調用

這個實現對於上篇文章中提到的Java使用裝飾器。上面也是一個裝飾器,實現最簡單的一個增長函很多天志的功能,可是若是這個額外功能是要去檢測傳入的參數時,這時上面的就不行了。這時12步輕鬆搞定python裝飾器中的例子仍是精妙的。數據結構

# 裝飾器
def wrapper(func):
    def checker(a, b): # 1
        if a.x < 0 or a.y < 0:
            a = Coordinate(a.x if a.x > 0 else 0, a.y if a.y > 0 else 0)
        if b.x < 0 or b.y < 0:
            b = Coordinate(b.x if b.x > 0 else 0, b.y if b.y > 0 else 0)
        ret = func(a, b)
        if ret.x < 0 or ret.y < 0:
            ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y > 0 else 0)
        return ret
    return checker


# 原函數
def add(a, b):
    return Coordinate(a.x + b.x, a.y + b.y)

# 使用裝飾    
add = wrapper(add)

細心你會發現,裝飾器函數的參數就是傳入的原函數,而內部函數的參數跟原函數如出一轍,最外層返回的是內部函數的引用,內部函數返回的是傳入參數的引用調用的結果閉包

這裏用到了函數做爲參數特性,固然還有些閉包的知識,具體請看 上面提到的博客連接,真的講的不錯。app

而上篇說到的Python裝飾 特性就是這個神奇的語法糖了,能夠這樣使用函數

# 原函數
@wrapper
def add(a, b):
    return Coordinate(a.x + b.x, a.y + b.y)

帶參數的裝飾器

若是要實現一個帶參數的裝飾器,那要怎麼寫呢日誌

def time_diff(s):
    def decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("[%s]執行程序所用時間: %s" % (s, end_time - start_time))
            return res
        return wrapper
    return decorator
    
@time_diff("polynomial_1")
def polynomial_1(n, x):
    res = 0
    for i in range(n):
        res += i*pow(x, i)
    return res

調用並執行輸出結果:code

print(polynomial_1(1, 5))

[duoxiangshi_1]執行程序所用時間: 4.76837158203125e-06
0

帶參數的裝飾器須要在不帶參數裝飾器外再定義一層函數,最外層函數的返回值是第二層函數的引用get

總結:多些多練,用於實際中,才能更加熟練。最近學數據結構與算法,寫些裝飾器用來看程序執行時間,真是再方便不過了!

相關文章
相關標籤/搜索