【问题标题】:Square braces not required in list comprehensions when used in a function在函数中使用时,列表推导中不需要方括号
【发布时间】:2012-06-12 14:14:32
【问题描述】:

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

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 !!!

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

【问题讨论】:

  • This link 也可能有用。
  • 还有字典和集合推导,以防你没听说过。

标签: python syntax list-comprehension


【解决方案1】:

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

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) 的原因:生成器版本只需存储单个值,而列表变体必须存储N 个值。因此,您应该始终使用不会产生副作用的生成器。

【讨论】:

  • 此外,生成器表达式通常使用较少的内存,因为没有创建中间列表。
【解决方案2】:

它们并不相同。

第一种形式,

[x for x in l]

是一个列表推导。另一个是生成器表达式,这样写:

(x for x in l)

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

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

PEP 289

【讨论】:

    【解决方案3】:

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

        (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>
    >>> 
    

    【讨论】:

      【解决方案4】:

      阅读此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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 1970-01-01
        • 2021-05-23
        • 2021-04-01
        相关资源
        最近更新 更多