单行循环迭代器与“if”filter?

愚蠢的问题:
我有一个简单的循环,然后是一个简单的if语句:

for airport in airports: if airport.is_important: 

我想知道如果我能以某种方式把它写成一行。
所以,是的,我可以这样做:

 for airport in (airport for airport in airports if airport.is_important): 

但它却是如此愚蠢和多余( for airport in airport for airport in airports... )。
有没有更好的办法?

不,没有更短的路。 通常,你甚至会把它分成两行:

 important_airports = (airport for airport in airports if airport.is_important) for airport in important_airports: # do stuff 

这是更灵活,更容易阅读,仍然不消耗太多的内存。

你可以做

 for airport in filter(lamdba x: x.is_important, airports): # do stuff... 

我会在循环中使用负面防守。 它是可读的,不会引入额外的缩进级别。

 for airport in airports: if not airport.is_important: continue <body of loop> 

Mabe这个,但它或多或less是相同的详细…

 import itertools for airport in itertools.ifilter(lambda x: x.is_important, airports): ... 

这是python的devise哲学。 如果你把太多的话放在一条线上,应该分成几行来帮助那些追随你的人。 列表和生成器expression式更多地用于在位转换迭代 – 制作更可读的mapfilterforms。

以下是其他一些filter版本的替代方法:

 from operator import attrgetter as attr for airport in filter(attr('is_important'), airports): ... 

这具有相当简洁的优点,并让您使用点符号attr('first_class.is_full')。

你也可以把类似的东西(或一个使用列表理解的版本)放到一个效用函数filter_by_attr中。 那么你可以这样做:

 for airport in filter_by_attr(airports, 'is_important'): ... 

尽pipe如此,我仍然认为e-satis是正确的把它放在一个新的variables中,不pipe你使用什么方法。 这样做更加清楚,特别是如果使用不完全匹配有问题的属性名称(或者标准更复杂)。

我唯一要注意的是,如果你发现自己在几个地方使用了这个,也许你应该使机场成为一个特殊的集合,'important_airports'是@property,它返回已过滤的集合。 或者其他抽象来隐藏过滤(如服务调用)。

使用列表理解(只有机场是对象列表):

 for airport in [a for a in airports if a.is_important]: