关键字参数解析最佳实践

30

有没有更加紧凑/高效的方法来完成这个任务?

    for key in kwargs:
        if key == 'log':
            self.log = kwargs[key]
        elif key == 'bin':
            self.bin = kwargs[key]
        elif key == 'pid':
            self.pid = kwargs[key]
        elif key == 'conf':
            self.conf = kwargs[key]
7个回答

51
为了实现你所问的功能,你可以使用:
for key in ('log', 'bin', 'pid', 'conf'):
    if key in kwargs:
        setattr(self, key, kwargs[key])
或者
self.__dict__.update((key, kwargs[key])
                     for key in ('log', 'bin', 'pid', 'conf')
                     if key in kwargs)

然而,我通常更喜欢像这样的东西:

def f(log=None, bin=None, pid=None, conf=None):
    self.log = log
    self.bin = bin
    self.pid = pid
    self.conf = conf

虽然还有些重复,但是这段代码真的很容易阅读。所有属性都被初始化,无论相应的关键字参数是否被传递进来,而函数的签名清晰地记录了参数及其默认值。


8
不错!使用默认值可以让代码更短:for key in (...): setattr(self, key, kwargs.get(key)) - pajton
@pajton: 当然,但我尽量保持接近原始帖的代码。 - Sven Marnach
1
如果这些参数有默认值,那么就不需要。如果kwargs.get(key)没有找到对应的键,则会返回None - pajton
当kwargs需要转发到内部调用时,还有kwargs.pop(key [,default])。如果未找到键且未给出默认值,则此函数会引发关键错误,因此kwargs.pop(key,None)是有意义的。 - Yuri Feldman
@SvenMarnach 我喜欢第一个例子,但如果我有一个独立的函数,如何实现相同的功能呢?我没有自己定义,因此我会得到一个错误“setattr(self, key, kwargs[key]) NameError: name 'self' is not defined"。 - Valentyn
显示剩余2条评论

29
self.log = kwargs.get('log', default_log)
self.bin = kwargs.get('bin', default_bin)
self.pid = kwargs.get('pid', default_pid)
self.conf = kwargs.get('conf', default_conf)

这有一个额外的优点,self.log 无论如何都会被分配(AttributeError 意味着你的代码非常糟糕,仅此而已。始终确保一切都被分配了)。无需额外的 self.log = default_log 行。您可以省略默认值以获取 None

当我需要在类外部访问kwargs时,我发现这比setattr更有用,例如在模块级别。 - Inyoung Kim 김인영

10

如果在 get() 中提供的键不在字典中,则结果为 None

self.log = kwargs.get('log')
self.bin = kwargs.get('bin')
self.pid = kwargs.get('pid')
self.conf = kwargs.get('conf')

4
for k,v in kwarg.iteritems():
   setattr(self, k, v)

setattr(self, "bin", "val") 的作用类似于调用 self.bin = "val"

然而像 @Sven Marnach 所建议的那样,拥有一个白名单会更加理想。


2
for k,v in kw.items():
   setattr(self, k, v)

1

self.__dict__.update(kwargs)


4
这非常危险并且推荐的方式不健壮。 - user395760

0

我的解决方案是:

for key in ('log', 'bin', 'pid', 'conf'):
    setattr(self, key, kwargs.get(key, None))

在此模式下,所有属性都将被初始化。
当我有大量属性时,我更喜欢创建一个列表,以便更容易阅读,就像这样:
kwargs_list = [
    "log",
    "bin",
    "pin",
    "conf"
]

for key in kwargs_list:
    setattr(self, key, kwargs.get(key, None))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接