为什么以下两行代码之间存在差异?

时间:2014-01-25 01:04:56

标签: python

total = sum([float(item) for item in s.split(",")])


total = sum(float(item) for item in s.split(","))

来源:https://stackoverflow.com/a/21212727/1825083

4 个答案:

答案 0 :(得分:6)

第一个使用list comprehension来构建所有浮点值的列表。

第二个使用generator expression来构建一个生成器,该生成器只根据请求构建每个浮点值,一次一个。当列表非常大时,这会节省大量内存。

生成器表达式也可能更快(因为它允许工作流水线,避免内存分配时间)或更慢(因为它增加了一些开销),但这通常不是在它们之间进行选择的好理由。只需遵循这个简单的经验法则:

如果您需要一个列表(或者,更可能的是,您可以存储的内容,多次循环,打印输出等),请构建一个列表。如果您只需要遍历值,请不要构建列表。

在这种情况下,显然,您不需要列表,因此请关闭方括号。


在Python 2.x中,还有一些其他的细微差别;在3.x中,列表推导实际上被定义为仅在生成器表达式上调用list函数。 (虽然至少3.0-3.3中存在一个小错误,如果你去寻找它很难找到它...)

答案 1 :(得分:5)

第一个列表,而第二个列表是生成器表达式。在没有sum()函数调用的情况下尝试它们。

In [25]: [float(a) for a in s.split(',')]
Out[25]: [1.23, 2.4, 3.123]

In [26]: (float(a) for a in s.split(','))
Out[26]: <generator object <genexpr> at 0x0698EF08>

In [27]: m = (float(a) for a in s.split(','))

In [28]: next(m)
Out[28]: 1.23

In [29]: next(m)
Out[29]: 2.4

In [30]: next(m)
Out[30]: 3.123

因此,第一个表达式首先在内存中创建整个列表,然后计算总和,而第二个表达式只获取表达式中的下一个项目并将其添加到当前总计中。 (更高效的内存)

答案 2 :(得分:2)

正如其他人所说,第一个创建了一个列表,而第二个创建了一个生成所有值的生成器。您可能关心这一点的原因是创建列表会立即将所有元素放入内存中,而使用生成器,您可以在生成它们时处理它们而无需将它们全部存储起来,这对于非常大量的数据可能很重要

答案 3 :(得分:1)

第一个创建一个列表,并对列表中的数字求和。这是一个总和

中的列表理解

第二个项依次计算每个项目并将其添加到运行总计中,并在所有项目都用尽时将运行总计作为总和返回。这是一种生成器理解 它根本不创建列表,这意味着它不需要额外的时间来为列表分配内存并填充它。这也意味着它具有更好的空间复杂性,因为它只使用恒定的空间(用于调用float;除了调用split,这两行都是这样做的)