在Python中,使用列表推导或for-each循环是否更好?

时间:2010-05-17 14:03:18

标签: python coding-style foreach list-comprehension

以下哪项更好用?为什么?

方法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?我假设没有性能差异,但我可能错了。这两种技术的优点和缺点是什么?

(代码取自Dive into Python

7 个答案:

答案 0 :(得分:37)

如果正在为其副作用进行迭代(就像在“print”示例中那样),则循环更清晰。

如果执行迭代以构建复合值,则列表推导通常更具可读性。

答案 1 :(得分:26)

您选择的特定代码示例并未证明列表理解的任何优势,因为它(错误地)用于打印的繁琐任务。在这个简单的例子中,我会选择简单的for循环。

在许多其他情况下,您需要为另一个函数或方法提供实际列表,列表理解是最简单,最易读的方法。

通过将print示例替换为涉及创建另一个实际列表的示例,通过在for循环的每次迭代中附加一个示例,可以清楚地显示列表comp的优越性的示例:

L = []
for x in range(10):
    L.append(x**2)

提供相同的L

L = [x**2 for x in range(10)]

答案 2 :(得分:14)

我发现第一个例子更好 - 更简洁,更清晰,更易读。

在我看来,毕竟,最好的方法是:#/ p>

  

应该为人们编写程序   阅读,只是偶然的   要执行的机器。

- 来自Abelson和Sussman的“计算机程序的结构和解释”

顺便说一下,既然你刚刚开始学习Python,那就马上开始学习new String Formatting syntax

for k, v in os.environ.items():
    print "{0}={1}".format(k, v)

答案 3 :(得分:13)

列表理解的速度是显式循环的两倍多。基于Ben James的变异,但用更简单的x + 2函数替换x ** 2,两种选择是:

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时,列表理解是一件令人难以理解的奇怪事情! :-O但是一旦我习惯它,它就变成了一个非常好的简写符号。如果你要精通Python,你必须掌握列表理解。

答案 4 :(得分:4)

我认为第一个,因为:

  • 它没有构建一个巨大的字符串。
  • 它没有构建庞大的列表(可以通过删除[]轻松修复生成器。)

在这两种情况下,您都以相同的方式访问项目(使用字典迭代器)。

答案 5 :(得分:3)

列表推导应该在C级别运行,所以如果有很大的循环,列表推导是不错的选择。

答案 6 :(得分:2)

我同意@ Ben,@ Tim,@ Steven:

  • 可读性是最重要的事情(做“导入此”以提醒自己是什么)
  • listcomp可能会或可能不会比迭代循环版本快得多......它取决于所做的函数调用的总数
  • 如果决定使用包含大型数据集的listcomps,最好使用生成器表达式而不是

示例:

print "\n".join("%s=%s" % (k, v) for k,v in os.environ.iteritems())

在上面的代码片段中,我进行了两次更改...我用genexp替换了listcomp,并将方法调用更改为iteritems()。 [这种趋势正在向前发展,如在Python 3中,iteritems()替换并重命名为items()。]