在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() 。]