列表理解与 lambda + 筛选器
我有一个列表,我想按项目的属性进行筛选。
以下哪项是首选(可读性,性能,其他原因)?
xs = [x for x in xs if x.attribute == value]
xs = filter(lambda x: x.attribute == value, xs)
我有一个列表,我想按项目的属性进行筛选。
以下哪项是首选(可读性,性能,其他原因)?
xs = [x for x in xs if x.attribute == value]
xs = filter(lambda x: x.attribute == value, xs)
奇怪的是,不同人的美丽有多大的不同。我发现列表理解比+更清晰,但使用您认为更容易的。filter
lambda
有两件事可能会减慢您对 .filter
第一个是函数调用开销:一旦你使用Python函数(无论是由还是创建),过滤器很可能会比列表理解慢。几乎可以肯定的是,这并不重要,在你确定代码的时间并发现它是一个瓶颈之前,你不应该过多地考虑性能,但差异将在那里。def
lambda
可能适用的另一个开销是 lambda 被强制访问作用域变量 ()。这比访问局部变量慢,在Python 2.x中,列表理解仅访问局部变量。如果您使用的是Python 3.x,则列表推导在单独的函数中运行,因此它也将通过闭包进行访问,并且此差异将不适用。value
value
要考虑的另一个选项是使用生成器而不是列表推导:
def filterbyvalue(seq, value):
for el in seq:
if el.attribute==value: yield el
然后,在你的主代码中(这是可读性真正重要的地方),你已经用一个希望有意义的函数名称替换了列表理解和过滤器。
这在Python中是一个有点宗教问题。尽管Guido考虑从Python 3中删除map
,filter
和reduce
,但还是有足够的反弹,最终只是从内置移动到functools.reduce。reduce
就个人而言,我发现列表理解更容易阅读。从表达式中发生的情况更明确,因为所有行为都在表面上而不是在过滤器函数内部。[i for i in list if i.attribute == value]
我不会太担心这两种方法之间的性能差异,因为它是微不足道的。我真的只会优化它,如果它被证明是你的应用程序中的瓶颈,这是不太可能的。
另外,由于BDFL想要从语言中消失,那么肯定会自动使列表理解更加Pythonic ;-)filter