本文實例講述了Python裝飾器用法。分享給大家供大家參考,具體如下:
寫裝飾器
裝飾器只不過是一種函數,接收被裝飾的可調用對象作為它的唯一參數,然后返回一個可調用對象(就像前面的簡單例子)
注意重要的一點,當裝飾器被應用到被裝飾函數上時,裝飾器代碼本身就會運行,而不是當被裝飾函數被調用時.理解這個很關鍵,接下來的幾個例子的講解過程也會變得很清楚
第一個例子: 函數注冊
看下面簡單的函數注冊:
registry = []def register(decorated): registry.append(decorated) return decorated
注冊器方法是一個簡單的裝飾器。它追加位置參數,也就是被裝飾函數到registry變量中,然后不做改變地返回被裝飾方法。任何接受register裝飾器的方法會把它自己追加到registry變量上。
@registerdef foo(): return 3@registerdef bar(): return 5
如果你訪問了registry,可以很容易地在上面迭代并執行里面的函數。
answers = []for func in registry: answers.append(func())
answers 列表現在回包含 [3, 5]. 這是因為函數已按次序執行,并且它們的返回值被追加到 answers中.
對于現有的函數注冊,有幾類簡單的應用,例如添加“鉤子(hooks)”到代碼中,這樣的話自定義的功能在條件事件之前或之后運行。 下面的Registry類能夠處理這種情況:
class Registry(object): def __init__(self): self._functions = [] def register(self, decorated): self._functions.append(decorated) return decorated def run_all(self, *args, **kwargs): return_values = [] for func in self._functions: return_values.append(func(*args, **kwargs)) return return_values
這個類里的register方法讓然像之前一樣按同樣方法工作。用一個綁定(bound)的方法作為裝飾器完全沒問題。它接收self作為第一參數(像任何綁定方法一樣),并且需要一個額外的位置參數,那就是被裝飾函數,通過創建幾個不同的 registry實例,你可以擁有一些完全分開的注冊器。使用相同函數并且,用超過一個注冊器注冊它也是可行的,像下面展示的一樣 :
a = Registry()b = Registry()@a.registerdef foo(x=3): return x@b.registerdef bar(x=5): return x@a.register@b.registerdef baz(x=7): return x
運行兩個注冊器的run_alll方法,得到如下結果:
a.run_all() # [3, 7]b.run_all() # [5, 7]
注意,run_all 方法能夠使用參數,當它們運行時會把參數傳給內部函數
a.run_all(x=4) # [4, 4]
運行時包裝代碼
以上這些裝飾器都很簡單,因為被裝飾方法被傳遞后未經更改。然而,有些時候當被裝飾方法執行時,你想要運行額外的功能。你通過返回一個添加了相關功能并且在它執行過程中調用被裝飾方法的不同的可調用對象來實現。
新聞熱點
疑難解答