在Python中,使用列表parsing还是for-each循环更好?
以下哪个更好用,为什么?
方法1:
for k, v in os.environ.items(): print "%s=%s" % (k, v)
方法2:
print "\n".join(["%s=%s" % (k, v) for k,v in os.environ.items()])
我倾向于把第一个理解为更容易理解,但这可能只是因为我是Python新手,列表理解对我来说还是有些陌生的。 第二种方式认为是更多Pythonic? 我假设没有性能差异,但我可能是错的。 这两种技术的优点和缺点是什么?
(代码取自潜入Python )
如果迭代正在完成其副作用(如在“打印”示例中),则循环更清晰。
如果为了构build复合值而执行迭代,那么列表parsing通常更具可读性。
您select的特定代码示例没有显示列表理解的任何优点,因为它正被(错误)用于打印的琐碎任务。 在这个简单的情况下,我会select简单for
循环。
在许多其他情况下,您将需要为另一个函数或方法提供一个实际列表,而列表理解是最简单和最可读的方法。
通过在for
循环的每次迭代中追加一个,可以通过将print
示例replace为创build另一个实际列表的例子来清楚地显示列表comp的优越性。
L = [] for x in range(10): L.append(x**2)
给出与L
相同的L
:
L = [x**2 for x in range(10)]
我发现第一个例子更好 – 不那么冗长,更清晰和更具可读性。
在我看来,毕竟是最好的,
程序应该是为人们阅读而写的,而且只是偶然地让机器去执行。
– 来自Abelson和Sussman的“计算机程序的结构和解释”
顺便说一下,因为您刚刚开始学习Python,请立即开始学习新的string格式化语法 :
for k, v in os.environ.items(): print "{0}={1}".format(k, v)
列表理解速度是显式循环的两倍以上。 基于本詹姆斯的变化,但用一个更微不足道的x + 2函数replacex ** 2,这两个select是:
def foo(n): L = [] for x in xrange(n): L.append(x+2) return L def bar(n): return [x+2 for x in xrange(n)]
时间结果:
In [674]: timeit foo(1000) 10000 loops, best of 3: 195 us per loop In [675]: timeit bar(1000) 10000 loops, best of 3: 81.7 us per loop
名单理解大幅度获胜。
我认为,可读性应该是性能优化的一个优先事项。 然而,可读性是在旁观者的眼中。 当我第一次学习Python时,列表理解是一件奇怪的事情,我觉得很难理解! : – 但是一旦我适应了它,它变成了一个非常好的简短符号。 如果你要精通Python,你必须掌握列表理解。
我认为第一个是因为:
- 它不会build立一个巨大的string。
- 它不会build立一个巨大的列表(可以很容易地用一个生成器修复,通过删除
[]
)。
在这两种情况下,都以相同的方式访问项目(使用字典迭代器)。
列表推导应该在C级运行,所以如果有巨大的循环,列表推断是不错的select。
我同意@Ben,@Tim,@Steven:
- 可读性是最重要的事情(做“input这个”来提醒自己什么是)
- 一个listcomp可能会或可能不会比迭代循环版本快得多…这取决于所做的函数调用总数
- 如果您决定使用大型数据集的listcomps,最好使用生成器expression式
例:
print "\n".join("%s=%s" % (k, v) for k,v in os.environ.iteritems())
在上面的代码片段中,我做了两个更改…我用一个genexpreplace了listcomp,并将方法调用改为iteritems()
。 [这个趋势是在Python 3中向前推进, iteritems()
取代iteritems()
命名为items()
。]