我非常喜欢Python的列表理解,我认为它实际上比常规迭代更容易阅读。
我正在编写一个在**kwargs
中有可选参数的构造函数,可用于设置类'并且我想把它写成列表理解,但是有一个实际上没有做任何事情的清单似乎没有意义。考虑一下:
class Book(object):
attrs = ('id', 'title', 'authors',...)
def __init__(self, *args, **kwargs):
[setattr(self, attr, kwargs.get(attr)
for attr in O.attrs if kwargs.get(attr)]
虽然语法看起来很好,但我认为这是错误的编码,因为你已经创建了一个
列表[None, None, None...]
那只是坐在那里。是的,我知道它是在构造函数运行后收集的,但我仍然不喜欢它。如果我读了某人的代码,那我就不会感到沮丧。
是否有更好的方法可以完成迭代,如同列表理解一样干净,但不会创建无用的对象
编辑:
响应使用循环
class Book(object):
attrs = ('id', 'title', 'authors',...)
def __init__(self, *args, **kwargs):
for attr in attrs:
if kwargs.get(attr):
setattr(self, attr, kwargs.get(attr)
这是你们的意思吗?如果没有,那么写一个更好的方法呢?
答案 0 :(得分:3)
您可以使用生成器表达式直接更新instance __dict__
attribute而不是列表解析:
class Book(object):
attrs = ('id', 'title', 'authors',...)
def __init__(self, *args, **kwargs):
self.__dict__.update(
(attr, kwargs[k]) for k in kwargs.viewkeys() & self.attrs)
这也使用dictionary views;在Python 3中,只需使用kwargs.keys()
而不是kwargs.viewkeys()
。字典视图作为一个集合; & self.attrs
表达式生成kwargs
的键与属性列表之间的交集。
生成器表达式生成(key, value)
对,dict.update()
method的两个可接受输入之一。
更新self.__dict__
就好了; Python 2.7标准库在7个不同的位置使用这种技术,加上大约30个其他的突变案例。请注意,如果您使用描述符(@property
和/或其他自定义描述符),那么访问self.__dict__
会绕过这些描述符。
关于副作用的列表理解:只是不要。你确实在浪费周期创建一个立即丢弃的列表对象,混淆了对列表理解 的期望。
您还可以在常规setattr()
循环中将其与显式for
次调用结合使用:
for attr in kwargs.viewkeys() & self.attrs:
setattr(self, attr, kwargs[attr])
答案 1 :(得分:2)
怎么样:
for attr in [a for a in attrs if a in kwargs]:
setattr(self, attr, kwargs[attr])
这相当简单和甜蜜......
或者克里斯建议:
for attr in (a for a in attrs if a in kwargs):
会更好。 (生成器而不是列表)