[英]Passing default arguments to a decorator in python
我试图找到一种方法将我的函数的默认参数传递给装饰器。 我不得不说我对装饰业务还很陌生,所以也许我只是没有正确理解它,但我还没有找到任何答案。
所以这是我从 Python functools.wraps
手册页修改的示例。
from functools import wraps
def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
print('Calling decorated function')
print('args:', args)
print('kwargs:', kwds)
return f(*args, **kwds)
return wrapper
@my_decorator
def example(i, j=0):
"""Docstring"""
print('Called example function')
example(i=1)
我也希望j=0
被传递。 所以输出应该是:
Calling decorated function
args: ()
kwargs: {'i': 1, 'j': 0}
Called example function
但相反我得到
Calling decorated function
args: ()
kwargs: {'i': 1}
Called example function
默认参数是函数签名的一部分。 它们不存在于装饰器调用中。
要在包装器中访问它们,您需要将它们从函数中取出,如本问题所示。
import inspect
from functools import wraps
def get_default_args(func):
signature = inspect.signature(func)
return {
k: v.default
for k, v in signature.parameters.items()
if v.default is not inspect.Parameter.empty
}
def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
print('Calling decorated function')
print('args:', args)
kwargs = get_default_args(f)
kwargs.update(kwds)
print('kwargs:', kwargs)
return f(*args, **kwds)
return wrapper
@my_decorator
def example(i, j=0):
"""Docstring"""
print('Called example function')
example(i=1)
输出:
Calling decorated function
args: ()
kwargs: {'i': 1, 'j': 0}
Called example function
您可以使用__defaults__
特殊属性获取默认参数值。
def my_decorator(f):
@wraps(f)
def wrapper(*args, **kwds):
print('def args values', f.__defaults__)
return f(*args, **kwds)
return wrapper
参考:在https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy 中查找__defaults__
包含具有默认值的参数的默认参数值的元组,如果没有参数具有默认值,则为 None
获取 args 和 kwargs 的确切列表有点棘手,因为您可以将位置 args 作为 kwarg 传递,反之亦然。 较新版本的 python 还添加了仅位置参数或仅关键字参数。
但是, inspect.signature
有一种可以应用默认值的机制:调用.bind(*args, **kwargs)
后跟.apply_defaults()
。 这可以为您提供一个有效的字典,其中包含函数的所有参数。 在 OP 的示例中,这变为:
from functools import wraps
import inspect
def my_decorator(f):
sig = inspect.signature(f)
@wraps(f)
def wrapper(*args, **kwds):
bound = sig.bind(*args, **kwds)
bound.apply_defaults()
print('Calling decorated function')
print('called with:', bound.arguments)
return f(*args, **kwds)
return wrapper
@my_decorator
def example(i, j=0):
"""Docstring"""
print('Called example function')
example(i=1)
这会在 Python 3.9 上输出以下内容:
Calling decorated function
called with: OrderedDict([('i', 1), ('j', 0)])
Called example function
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.