我有一个可以用不同的参数组合构建的类,但是我有一个必需的参数列表。以下是我目前的检查方式:
# check for the required arguments
rqrd_args = ['a', 'b', 'c'] # required arguments
mssing_args = set(rqrd_args)-set(kwargs.keys())
if mssing_args:
error_lines = ['The following required arguments are missing:']
error_lines.extend(['\t%s'%x for x in mssing_args])
sys.exit('\n'.join(error_lines))
# pull from kwargs
self.a = kwargs['a']
self.b = kwargs['b']
self.c = kwargs['c']
我倾向于重复使用这段代码。我的问题是,我可以以某种方式用循环来替换“#pull from kwargs”部分,该循环遍历所需的参数列表,这样代码更通用吗?我有什么理由不想这样做吗?
答案 0 :(得分:5)
如果需要,请将它们作为常规参数:
def __init__(a, b, c, **kwargs):
self.a = a
self.b = b
self.c = c
# ... then the rest in kwargs
答案 1 :(得分:3)
我倾向于同意其他评论和答案,最好是制作这些常规参数,并允许任何Python错误随着错误的args传递而渗透。
但是,有时您可能需要进行一些特殊的验证过程。我并不赞同这是一个很好的设计选择,但也许它可能会发生。
在这种情况下,我会说要创建一个包含验证逻辑的装饰器:
def arg_validator(*arg_names):
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for arg in arg_names:
if arg not in kwargs:
# Do some handling here for missing arg
return func(*args, **kwargs)
return wrapper
return decorator
然后创建一个装饰的辅助函数,用函数构造你的类。
@arg_validator('a', 'b', 'c')
def my_class_maker(*args, **kwargs):
return MyClass(*args, **kwargs)
现在,如果调用my_class_maker(...)
,则在装饰函数检查关键字参数时将执行验证逻辑。如果所有需要的args都在那里,你将只返回创建的实例。
这具有额外的好处,验证逻辑是模块化的,并且与类本身的逻辑分开,因为验证的想法可能适用于许多不相关的类,每个类都没有真正的理由去关心为什么<该类的外部用户可能需要验证。
您甚至可以扩展我编写的装饰器并允许将可调用的函数传递给装饰器制作器,然后该调用可以封装验证行为,以便在未找到参数时执行。然后,甚至不必修复特定的验证行为。
答案 2 :(得分:2)
这应该可以解决问题:
for attr_name in rqrd_args:
setattr(self, attr_name, kwargs[attr_name])