![](/img/trans.png)
[英]Understanding how passing arguments to the decorated function works
[英]Passing optional keyword arguments to a decorated function
我想創建一個裝飾器,將可選關鍵字傳遞給它包裝的函數。 像這樣的東西:
@mydecorator
def dummy_without_magic_word():
print('hello world')
@mydecorator
def dummy_with_magic_word(magic_word):
print(magic_word)
基本上,如果被包裝的函數有一個特定的關鍵字,它應該由裝飾器提供; 否則,只需運行包裝的函數。
實現這一目標的正確方法是什么? 目前我只是想傳入關鍵字並檢查TypeError:
try:
output = fn(redirect=redirect, **kwargs)
except TypeError as e:
if 'unexpected keyword argument' not in str(e):
raise e
output = fn(*args, **kwargs)
但這似乎很脆弱/不直觀/奇怪。
為此,您可以使用inspect
模塊。 使用getfullargspec
函數,您可以訪問函數中定義的所有參數名稱。 一個注釋是,如果您想參數化傳遞給裝飾函數的默認值,您將需要一個裝飾器工廠。 這是一個代碼示例:
import inspect
def my_decorator(default_value): # define decorator factory
def decorator(fn): # define decorator
def inner(*args, **kwargs):
fn_args = inspect.getfullargspec(fn).args # recover decorated function
# arguments
if "magic_word" in fn_args: # check for argument
return fn(*args, magic_word=default_value, **kwargs)
else:
return fn(*args, **kwargs)
return inner
return decorator
@my_decorator(default_value='Goodbye World')
def function_1():
print('Hello World')
@my_decorator(default_value='Goodbye World')
def function_2(magic_word):
print(magic_word)
使用此裝飾器,以下代碼的結果將是:
>>> function_1()
'Hello World'
>>> function_2()
'Goodbye World'
請注意,如果您只有關鍵字參數,則必須稍微修改裝飾器:
def my_decorator(default_value): # define decorator factory
def decorator(fn): # define decorator
def inner(*args, **kwargs):
fn_args = inspect.getfullargspec(fn).args # recover decorated function
# arguments
fn_args += (inspect.getfullargspec(fn).kwonlyargs) # add kwonly args
if "magic_word" in fn_args: # check for argument
return fn(*args, magic_word=default_value, **kwargs)
else:
return fn(*args, **kwargs)
return inner
return decorator
@my_decorator(default_value='Goodbye World')
def function_3(a, *, magic_word):
print(a, magic_word)
>>> function_3(1)
1 Goodbye World
請注意,此實現有一個重要的限制,即您必須對要查找的參數名稱進行硬編碼。 情況就是這樣,因為 python 無法計算參數名稱的表達式。 例如,如果您嘗試此實現:
def my_decorator(search_word, default_value): # define decorator factory
def decorator(fn): # define decorator
def inner(*args, **kwargs):
fn_args = inspect.getfullargspec(fn).args # recover decorated function
# arguments
fn_args += (inspect.getfullargspec(fn).kwonlyargs) # add kwonly args
if search_word in fn_args: # check for argument
return fn(*args, search_word=default_value, **kwargs)
else:
return fn(*args, **kwargs)
return inner
return decorator
@my_decorator(search_word='magic_word', default_value='Goodbye World')
def function_4(magic_word):
print(magic_word)
運行代碼會引發錯誤:
>>> function_4()
Traceback (most recent call last):
File "/test.py", in <module>
function_4()
File "/test6.py", in inner
return fn(*args, search_word=default_value, **kwargs)
TypeError: function_4() got an unexpected keyword argument 'search_word'
語法是這樣的:
def decorator(*args, **kwargs):
print("Inside decorator")
def inner(func):
print("Inside inner function")
print("I like", kwargs['param'])
func()
# reurning inner function
return inner
@decorator(param = "Hello world")
def my_func():
print("Inside actual function")
或者:
@mydecorator
def dummy_with_magic_word(magic_word = 'hello world'):
print(magic_word)
要檢查參數名稱,您可以像這樣深入研究函數對象:
arguments = fn.__code__.co_varnames[:fn.__code__.co_argcount]
if "redirect" in arguments:
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.