[英]Validated Function Arguments in Python
我有一個功能
def func(a,b,c,d):
...
我正在嘗試編寫一個了解參數的裝飾器,並將其中一些記錄到另一個系統中。
def decorator(func):
def new_func(*args, **kwargs):
if (func.__name__ == 'func'):
a = ?
b = ?
c = ?
d = ?
else:
a = ?
b = ?
c = ?
d = ?
log_to_system(a, b, c, d)
return func(*args, **kwargs)
return new_func
問題是裝飾器沒有一種簡單的方法從args和kwargs中提取a,b,c,d值,因為用戶可以使用位置或關鍵字參數傳遞這些值。 我也希望保持這種通用性,因為這個裝飾器可以用於各種不同的功能。
是否有一個庫或實用程序可以輕松地從args和kwargs中提取參數的值?
一個簡單的方法是讓你的log_to_system
函數接受變量參數和變量關鍵字參數以及它實際記錄的已知參數,這樣你就可以簡單地將變量參數和變量關鍵字參數從裝飾函數傳遞給log_to_system
並讓解釋器為您提取參數a
, b
, c
和d
:
def log_to_system(a, b, c, d, *args, **kwargs):
print(a, b, c, d)
def decorator(func):
def new_func(*args, **kwargs):
log_to_system(*args, **kwargs)
return func(*args, **kwargs)
return new_func
@decorator
def func(a, b, c, d, e):
pass
func(1, 2, c=3, d=4, e=5)
這輸出:
1 2 3 4
或者,您可以使用inspect.signature
在將給定的變量參數和關鍵字參數綁定到裝飾函數的簽名之后獲取參數的dict,以便您可以僅使用所需的參數調用log_to_system
:
import inspect
def log_to_system(a, b, c, d):
print(a, b, c, d)
def decorator(func):
sig = inspect.signature(func)
def new_func(*args, **kwargs):
arguments = sig.bind(*args, **kwargs).arguments
log_to_system(**{k: arguments[k] for k in log_to_system.__code__.co_varnames})
return func(*args, **kwargs)
return new_func
@decorator
def func(a, b, c, d, e):
pass
func(1, 2, c=3, d=4, e=5)
這輸出:
1 2 3 4
您可以使用inspect
,工作示例:
import inspect
def deco(func):
signature = inspect.signature(func)
def _deco(*args, **kwargs):
binded = signature.bind(*args, **kwargs)
arguments = binded.arguments # OrderedDict
print(arguments.items())
return func(*args, **kwargs)
return _deco
@deco
def foo(a, b, c, d):
pass
@deco
def bar(d, c, b, a):
pass
foo(1, 2, c=3, d=4) # odict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
bar(1, a=2, b=3, c=4) # odict_items([('d', 1), ('c', 4), ('b', 3), ('a', 2)])
您可以使用此通用裝飾器來轉儲參數值:
def dump_args(func):
# Decorator to print function call details - parameters names and effective values
def wrapper(*func_args, **func_kwargs):
arg_names = func.__code__.co_varnames[:func.__code__.co_argcount]
args = func_args[:len(arg_names)]
defaults = func.__defaults__ or ()
args = args + defaults[len(defaults) - (func.__code__.co_argcount - len(args)):]
params = list(zip(arg_names, args))
args = func_args[len(arg_names):]
if args: params.append(('args', args))
if func_kwargs: params.append(('kwargs', func_kwargs))
return func(*func_args, **func_kwargs)
return wrapper
Credits屬於@aliteralmind,他在這篇StackOverflow 帖子中建議了這個裝飾器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.