在函数中使用时,列表推导中不需要方括号

时间:2012-06-12 14:14:32

标签: python syntax list-comprehension

我使用以下代码提交了拉取请求:

my_sum = sum([x for x in range(10)])

其中一位评论员建议:

my_sum = sum(x for x in range(10))

(区别在于缺少方括号)。

我很惊讶第二种形式似乎是相同的。但是当我尝试在第一个工作的其他环境中使用它时,它失败了:

y = x for x in range(10)
        ^ SyntaxError !!!

这两种形式是否相同?为什么在功能中不需要方括号是否有任何重要原因?或者这只是我必须知道的事情?

4 个答案:

答案 0 :(得分:18)

这是一个生成器表达式。要使它在独立的情况下工作,请使用大括号:

y = (x for x in range(10))

和y成为发电机。您可以迭代生成器,因此它适用于需要迭代的地方,例如sum函数。

用法示例和陷阱:

>>> y = (x for x in range(10))
>>> y
<generator object <genexpr> at 0x0000000001E15A20>
>>> sum(y)
45

保持发电机周围时要小心,你只能经历一次。因此,在上述情况之后,如果您再次尝试使用sum,则会发生这种情况:

>>> sum(y)
0

因此,如果您通过一个生成器实际上是一个列表或一组或类似的东西,你必须要小心。如果函数或类存储参数并尝试多次迭代它,则会遇到问题。例如,考虑一下:

def foo(numbers):
    s = sum(numbers)
    p = reduce(lambda x,y: x*y, numbers, 1)
    print "The sum is:", s, "and the product:", p
如果你把它交给发电机,它将会失败:

>>> foo(x for x in range(1, 10))
The sum is: 45 and the product: 1

您可以轻松地从生成器生成的值中获取列表:

>>> y = (x for x in range(10))
>>> list(y)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

您可以使用它来修复上一个示例:

>>> foo(list(x for x in range(1, 10)))
The sum is: 45 and the product: 362880

但请记住,如果从生成器构建列表,则需要存储每个值。在你有很多物品的情况下,这可能会使用更多的内存。

为什么在您的情况下使用发电机?

低得多的内存消耗是sum(generator expression)优于sum(list)的原因:生成器版本只需存储单个值,而list-variant必须存储N个值。因此,您应始终使用不会产生副作用的发生器。

答案 1 :(得分:4)

它们不完全相同。

第一种形式,

[x for x in l]

是列表理解。另一个是生成器表达式,因此写成:

(x for x in l)

它返回一个生成器,而不是列表。

如果生成器表达式是函数调用中的唯一参数,则可以跳过其括号。

请参阅PEP 289

答案 2 :(得分:2)

第一个是列表理解,其中第二个是生成器表达式

    (x for x in range(10))
    <generator object at 0x01C38580>
    >>> a = (x for x in range(10))
    >>> sum(a)
    45
    >>> 

使用大括号括号:

>>> y = (x for x in range(10))
>>> y
<generator object at 0x01C3D2D8>
>>> 

答案 3 :(得分:0)

阅读此PEP: 289

  

例如,以下求和代码将在内存中构建完整的正方形列表,迭代这些值,并且当不再需要引用时,删除列表:

sum([x*x for x in range(10)])
     

通过使用生成器表达式来节省内存:

sum(x*x for x in range(10))
     

随着数据量变大,生成器表达式往往表现更好,因为它们不会耗尽缓存内存,并允许Python在迭代之间重用对象。

使用支撑产品生成器:

>>> y = (x for x in range(10))
>>> y
<generator object <genexpr> at 0x00AC3AA8>