Python 记录函数的所有参数,但不使用参数名称
假设我得到了以下函数:Python 记录函数的所有参数,但不使用参数名称,python,python-3.x,Python,Python 3.x,假设我得到了以下函数: def do_something(arg_1, arg_2, arg_3): logger.info('arg_1: {0} arg_2: {1} arg_3: {2}'.format(arg_1, arg_2, arg_3)) print('Doing something..') 有没有一种优雅的方法可以记录函数的所有参数而不列出参数名?我相信这是深入研究装饰器的最佳时机。请看以下内容: def log_args(function): @fu
def do_something(arg_1, arg_2, arg_3):
logger.info('arg_1: {0} arg_2: {1} arg_3: {2}'.format(arg_1, arg_2, arg_3))
print('Doing something..')
有没有一种优雅的方法可以记录函数的所有参数而不列出参数名?我相信这是深入研究装饰器的最佳时机。请看以下内容:
def log_args(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
logger.info(', '.join(str(x) for x in args))
return function(*args, **kwargs)
return wrapper
@functools.wrapps
行是可选的
现在,按照如下方式装饰您的功能:
@log_args
def do_something(arg1, arg2):
print('doing something..')
说明:@log_args
行与执行以下操作相同:
do_something = log_args(do_something)
现在,这个log_args
接受函数并进入其局部范围。在此范围内,定义了另一个函数,称为wrapper。此函数包含将参数格式化为字符串的记录器。然后从包装器返回函数的结果。为了确保dou\u something
仍然是一个函数,我返回包装器
。现在,当调用dou\u something
时,实际上调用了包装器,并执行上述过程
我之所以使用decorator,是因为我可以在函数定义中保留显式的names参数,但是在decorator中,我可以使用
*args
将这些参数打包到一个列表中,即使函数本身只有命名的args。注意:关于保留参数的最后一点,我不是100%确定。事实上,我认为这根本不是真的。我相信这是深入研究装饰师的最佳时机。请看以下内容:
def log_args(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
logger.info(', '.join(str(x) for x in args))
return function(*args, **kwargs)
return wrapper
@functools.wrapps
行是可选的
现在,按照如下方式装饰您的功能:
@log_args
def do_something(arg1, arg2):
print('doing something..')
说明:@log_args
行与执行以下操作相同:
do_something = log_args(do_something)
现在,这个log_args
接受函数并进入其局部范围。在此范围内,定义了另一个函数,称为wrapper。此函数包含将参数格式化为字符串的记录器。然后从包装器返回函数的结果。为了确保dou\u something
仍然是一个函数,我返回包装器
。现在,当调用dou\u something
时,实际上调用了包装器,并执行上述过程
我之所以使用decorator,是因为我可以在函数定义中保留显式的names参数,但是在decorator中,我可以使用
*args
将这些参数打包到一个列表中,即使函数本身只有命名的args。注意:关于保留参数的最后一点,我不是100%确定。事实上,我不认为这是真的。要扩展@NChauhan的答案,如果您希望不仅能够记录位置参数的值,还能够记录位置参数和关键字参数的名称以及它们的给定值和默认值,那么:
@log_args
def do_something(arg_1, arg_2, arg_3='world'):
pass
do_something(2, arg_2='hello')
can输出:
do_something called with arg_1: 2, arg_2: 'hello', arg_3: 'world'
您可以与您的装饰师一起使用inspect.signature
:
import inspect
from functools import wraps
def log_args(func):
@wraps(func)
def wrapper(*args, **kwargs):
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
print('{} called with {}'.format(func.__name__, ', '.join('{}: {}'.format(name, repr(value)) for name, value in bound.arguments.items())))
return func(*args, **kwargs)
sig = inspect.signature(func)
return wrapper
要扩展@NChauhan的答案,如果您希望不仅能够记录位置参数的值,还能够记录位置参数和关键字参数的名称及其给定值和默认值,以便:
@log_args
def do_something(arg_1, arg_2, arg_3='world'):
pass
do_something(2, arg_2='hello')
can输出:
do_something called with arg_1: 2, arg_2: 'hello', arg_3: 'world'
您可以与您的装饰师一起使用inspect.signature
:
import inspect
from functools import wraps
def log_args(func):
@wraps(func)
def wrapper(*args, **kwargs):
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
print('{} called with {}'.format(func.__name__, ', '.join('{}: {}'.format(name, repr(value)) for name, value in bound.arguments.items())))
return func(*args, **kwargs)
sig = inspect.signature(func)
return wrapper