簡單裝飾器
上述**在 python 中有更簡單、更優雅的表示:def my_decorator(func):
func()
def greet():
print('hello world')
greet = my_decorator(greet)
greet()
# 輸出
# hello world
def my_decorator(func):
func()
@my_decorator
def greet():
print('hello world')
greet()
# 輸出
# hello world
帶引數的裝飾器
def my_decorator(func):
func(*args, **kwargs)
@my_decorator
def greet(message):
print(message)
greet('hello world')
# 輸出
# hello world
自定義引數的裝飾器
def repeat(num):
def my_decorator(func):
for i in range(num):
func(*args, **kwargs)
return my_decorator
@repeat(4)
def greet(message):
print(message)
greet('hello world')
# 輸出:
# hello world
# hello world
# hello world
# hello world
原函式還是原函式嗎?
試著列印出 greet() 函式的一些元資訊:
為了解決這個問題,通常使用內建的裝飾器greet.__name__
## 輸出
help(greet)
# 輸出
@functools.wrap
,它會幫助保留原函式的元資訊(也就是將原函式的元資訊,拷貝到對應的裝飾器函式裡)。
import functools
def my_decorator(func):
@functools.wraps(func)
func(*args, **kwargs)
@my_decorator
def greet(message):
print(message)
greet.__name__
# 輸出
'greet'
實際上,類也可以作為裝飾器。類裝飾器主要依賴於函式__call__()
,每當你呼叫乙個類的示例時,函式__call__()
就會被執行一次。
我們定義了類 count,初始化時傳入原函式class count:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs)
@count
def example():
print("hello world")
example()
# 輸出
num of calls is: 1
hello world
example()
# 輸出
num of calls is: 2
hello world
func()
,而__call__()
函式表示讓變數 num_calls 自增 1,然後列印,並且呼叫原函式。因此,在我們第一次呼叫函式example()
時,num_calls 的值是 1,而在第二次呼叫時,它的值變成了 2 PYTHON高階函式和裝飾器
定義 裝飾器的本質是函式,用來裝飾其他的函式,為其他的函式新增功能。函式修飾符 用做函式的修飾符,可以在模組或者類的定義層內對函式進行修飾,出現在函式定義的前一行,不允許和函式定義在同一行乙個修飾符就是乙個函式,它將被修飾的函式作為引數,並返回修飾後的同名函式或其他可呼叫的東西 原則 1 不能修改被...
Python高階函式 裝飾器
由於函式也是乙個物件,而且函式物件可能被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2018 4 11 f now f 2018 4 11 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now 現在,假設我們要增強now 函式的...
Python 高階函式 裝飾器
裝飾器 定義裝飾器本身是乙個可呼叫物件,接收乙個函式作為引數,然後將其返回或替換成另乙個函式或可呼叫物件。可以理解成,原來那是一堵白牆,經過了一層裝飾,這層裝飾可能是漆也可能把牆掏空鑲進一層 變得金光閃閃,最後呈現在你眼前的就是裝飾後的樣子。可以把它完全當成常規函式來呼叫,其引數是另乙個函式。裝飾器...