[英]Why does a decorator function have a return value?
考慮以下示例。
def decorator(function_to_decorate):
def wrapper():
print('Entering', function_to_decorate.__name__)
function_to_decorate()
print('Exiting', function_to_decorate.__name__)
return wrapper
@decorator
def func():
print("Original function.")
func()
因為@decorator
語法只是func = my_decorator(func)
的簡寫,所以my_decorator
必須返回一些東西是合乎邏輯的。 我的問題是:為什么以這種方式定義裝飾器而不是沒有返回值: my_decorator(func)
? 返回包裝函數wrapper
的目的是什么?
裝飾器如何做不僅僅是一個簡單的包裝器?
def wrapper(function_to_decorate):
print('Entering', function_to_decorate.__name__)
function_to_decorate()
print('Exiting', function_to_decorate.__name__)
def func():
print("Original function.")
wrapper(func)
想象一下,如果您可以將裝飾器應用於常規變量賦值,如下所示:
def add1(x):
return x + 1
@add1
number = 5
函數裝飾器的類似行為是這樣的:
number = 5
number = add1(number)
這將導致將值6
分配給變量number
。 現在想象一下,裝飾器只是被調用而沒有返回任何東西:
number = 5
add1(number)
這段代碼不可能將6
賦給變量number
,因為number
是按值傳遞的,而不是按引用傳遞; 在 Python 中,函數不能為它無法訪問的完全不同范圍內的變量分配新值。
def
語句實際上是一種賦值; 它將函數分配給您定義它的名稱。 例如,函數定義def func(): pass
編譯為執行STORE_NAME
字節碼,即賦值:
1 0 LOAD_CONST 0 (<code object func at ...>)
3 LOAD_CONST 1 ('func')
6 MAKE_FUNCTION 0
9 STORE_NAME 0 (func)
因此,出於同樣的原因,函數裝飾器的行為與上述相同; 裝飾器函數不能在完全不同的范圍內將新函數重新分配給變量func
,因為func
是按值傳遞給裝飾器的,而不是通過引用。
func = decorator(func)
等價實際上有點誤導。 完全正確,當您使用裝飾器時,您在def
語句中定義的函數將直接傳遞給裝飾器,而不是在傳遞之前分配給本地名稱func
。 這是字節碼:
1 0 LOAD_NAME 0 (decorate)
3 LOAD_CONST 0 (<code object func at ...>)
6 LOAD_CONST 1 ('func')
9 MAKE_FUNCTION 0
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 STORE_NAME 1 (func)
一步步:
decorate
函數被加載到堆棧中,func
的代碼對象被加載到堆棧上,然后是字符串'func'
,然后MAKE_FUNCTION
指令將這兩個變成一個留在堆棧上的函數。CALL_FUNCTION
指令使用一個參數調用decorate
函數(仍在堆棧中),即func
函數。decorate
函數返回什么,都會留在堆棧中,並由STORE_NAME
指令分配給名稱func
。 因此,如果decorator
函數沒有返回任何內容,那么將沒有任何東西可以分配給名稱func
- 甚至不是def
語句中的原始函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.