如何在Python方法中忽略未使用的关键字参数?
Python方法如何忽略未使用的关键字参数?
问题场景
我有一个类,其中包含多个函数,这些函数的部分关键字参数设有默认值,但也可指定自定义值。不过这些函数使用的关键字参数各不相同。以下是最小可复现示例:
class Things(object): def __init__(self, **kwargs): self.other = 999 self.result = self.some_fcn(**kwargs) self.other2 = self.some_fcn2(**kwargs) def some_fcn(self, x=None, y=None): if x is None: x = 7 if y is None: y = 7 return x + y def some_fcn2(self, z=None): if z is None: z = -1 return self.other * z
以下测试用例可正常运行:
ans = Things().some_fcn() print("default, should be 14:", ans) ans = Things(x=1) print("should be 8:", ans.result)
但执行ans = Things(x=1, z=100)时会报错,因为some_fcn2不接收x参数:
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-50-5e7081adb4fb> in <module> 25 ans = Things().some_fcn(9, -2) 26 print("should be 7:", ans) ---> 27 ans = Things(x=1) 28 print("should be 8:", ans.result) 29 print("***") <ipython-input-50-5e7081adb4fb> in __init__(self, **kwargs) 3 self.other = 999 4 self.result = self.some_fcn(**kwargs) ----> 5 self.other2 = self.some_fcn2(**kwargs) 6 7 self.__dict__.update(kwargs) TypeError: some_fcn2() got an unexpected keyword argument 'x'
注:此前尝试在构造函数中添加self.__dict__.update(kwargs),但无法解决该错误。
解决方案
方案1:给方法添加**kwargs参数捕获多余参数
直接在每个方法的参数列表末尾加上**kwargs,多余的关键字参数会被自动吸收,不会触发TypeError:
class Things(object): def __init__(self, **kwargs): self.other = 999 self.result = self.some_fcn(**kwargs) self.other2 = self.some_fcn2(**kwargs) def some_fcn(self, x=None, y=None, **kwargs): # 添加**kwargs if x is None: x = 7 if y is None: y = 7 return x + y def some_fcn2(self, z=None, **kwargs): # 添加**kwargs if z is None: z = -1 return self.other * z
方案2:筛选kwargs后再传入方法
如果不想修改方法的参数签名,可以使用inspect模块获取方法的参数列表,从kwargs中筛选出该方法需要的参数再传入:
import inspect class Things(object): def __init__(self, **kwargs): self.other = 999 # 筛选some_fcn需要的参数 some_fcn_params = inspect.signature(self.some_fcn).parameters.keys() self.result = self.some_fcn(**{k: v for k, v in kwargs.items() if k in some_fcn_params}) # 筛选some_fcn2需要的参数 some_fcn2_params = inspect.signature(self.some_fcn2).parameters.keys() self.other2 = self.some_fcn2(**{k: v for k, v in kwargs.items() if k in some_fcn2_params}) def some_fcn(self, x=None, y=None): if x is None: x = 7 if y is None: y = 7 return x + y def some_fcn2(self, z=None): if z is None: z = -1 return self.other * z
这种方式更灵活,不需要修改原有方法的定义,适合方法较多或无法修改方法源码的场景。
方案3:使用函数装饰器封装参数过滤
如果多个方法都需要处理这种情况,可以封装一个装饰器来自动过滤多余参数:
import inspect def ignore_extra_args(func): sig = inspect.signature(func) def wrapper(*args, **kwargs): filtered_kwargs = {k: v for k, v in kwargs.items() if k in sig.parameters} return func(*args, **filtered_kwargs) return wrapper class Things(object): def __init__(self, **kwargs): self.other = 999 self.result = self.some_fcn(**kwargs) self.other2 = self.some_fcn2(**kwargs) @ignore_extra_args def some_fcn(self, x=None, y=None): if x is None: x = 7 if y is None: y = 7 return x + y @ignore_extra_args def some_fcn2(self, z=None): if z is None: z = -1 return self.other * z
装饰器可以复用,适合大量方法需要处理的场景。
内容的提问来源于stack exchange,提问作者a11
相关产品推荐
相关产品推荐

