Validated Function Arguments in Python
我有一个功能
1 2 | def func(a,b,c,d): ... |
我正在尝试编写一个能理解这些参数并将其中一些参数记录到另一个系统中的修饰符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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中提取参数值?
一个简单的方法是让你的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 | 1 2 3 4 |
号
或者,在将给定的变量参数和关键字参数绑定到修饰函数的签名之后,可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 | 1 2 3 4 |
号
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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)]) |
您可以使用此常规装饰器来转储参数值:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
。
学分属于@aliteralmind,他在stackoverflow帖子中建议这个装饰师。