我有一个接受回调的API方法。回调需要一个参数。
我希望此方法将第二个参数传递给接受它的回调。但是,我必须与仅接受原始参数的回调保持兼容性。 (实际上,我希望大多数用户不会在意这个附加参数,因此强迫他们明确地忽略它会很烦人。)
我知道可以使用inspect
完成此操作。我想知道是否有一个“惯用的”或常用的解决方案不太重。
答案 0 :(得分:4)
我认为您可以使用__code__查看回调所需的参数。
if callback.__code__.co_argcount == 2:
callback(arg1, arg2)
else:
callback(arg1)
此代码未经测试,但可以正常工作。
答案 1 :(得分:1)
一种更简单的解决方案是使用try
块先尝试使用第二个参数调用回调,然后再退回到except
块中仅使用一个参数进行调用:
try:
callback(first, second)
except TypeError as e:
if e.__traceback__.tb_frame.f_code.co_name != 'func_name':
raise
callback(first)
答案 2 :(得分:-1)
使用函数包装器:
from inspect import signature, Parameter
def ignore_extra_arguments(function):
positional_count = 0
var_positional = False
keyword_names = set()
var_keyword = False
for p in signature(function).parameters.values():
if p.kind == Parameter.POSITIONAL_ONLY:
positional_count += 1
elif p.kind == Parameter.POSITIONAL_OR_KEYWORD:
positional_count += 1
keyword_names.add(p.name)
elif p.kind == Parameter.VAR_POSITIONAL:
var_positional = True
elif p.kind == Parameter.KEYWORD_ONLY:
keyword_names.add(p.name)
elif p.kind == Parameter.VAR_KEYWORD:
var_keyword = True
if var_positional:
new_args = lambda args: args
else:
new_args = lambda args: args[:positional_count]
if var_keyword:
new_kwargs = lambda kwargs: kwargs
else:
new_kwargs = lambda kwargs: {
name: value for name, value in kwargs.items()
if name in keyword_names
}
def wrapped(*args, **kwargs):
return function(
*new_args(args),
**new_kwargs(kwargs)
)
return wrapped
它可以工作,但是有点蛮力。
一个简单的版本,假设function
没有关键字或可变参数:
from inspect import signature
def ignore_simple(function):
count = len(signature(function).parameters)
return lambda *args: function(*args[:count])