Python 在函数中使用时,列表理解中不需要方括号

Python 在函数中使用时,列表理解中不需要方括号,python,syntax,list-comprehension,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 !!! 这两种形式相同吗?函数中不需要方括号有什么重要原因吗?或者这只

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

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

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

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

y = (x for x in range(10))
y变成了一个发电机。您可以在生成器上迭代,这样它就可以在需要iterable的地方工作,例如
sum
函数

使用示例和陷阱:

>>> y = (x for x in range(10))
>>> y
<generator object <genexpr> at 0x0000000001E15A20>
>>> sum(y)
45
因此,如果您传递一个生成器,其中实际上需要一个列表、一个集合或类似的内容,那么您必须小心。如果函数或类存储参数并尝试多次迭代,则会遇到问题。例如,考虑这个:

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))
>>> y
<generator object <genexpr> at 0x00AC3AA8>
您可以从生成器生成的值轻松获取列表:

>>> 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(生成器表达式)
优于
sum(list)
的原因:生成器版本只需存储单个值,而列表变量必须存储N个值。因此,您应该始终使用不存在副作用风险的生成器。

第一个是列表压缩,第二个是生成器表达式

    (x for x in range(10))
    <generator object at 0x01C38580>
    >>> a = (x for x in range(10))
    >>> sum(a)
    45
    >>> 
(x代表范围(10)内的x)
>>>a=(范围(10)内x的x)
>>>总数(a)
45
>>> 
发电机使用支架:

>>> y = (x for x in range(10))
>>> y
<generator object at 0x01C3D2D8>
>>> 
>y=(x代表范围(10)中的x)
>>>y
>>> 

它们不完全相同

第一种形式,

[x for x in l]
是一个列表理解。另一个是生成器表达式,这样写:

(x for x in l)
它返回一个生成器,而不是列表

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

请参见阅读此

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

sum([x*x for x in range(10)])
通过使用生成器表达式来节省内存:

sum(x*x for x in range(10))
随着数据量的增大,生成器表达式的性能会更好,因为它们不会耗尽缓存内存,并且允许Python在迭代之间重用对象。

在发电机上使用支架产品:

>>> foo(x for x in range(1, 10))
The sum is: 45 and the product: 1
>>> y = (x for x in range(10))
>>> y
<generator object <genexpr> at 0x00AC3AA8>
>y=(x代表范围(10)中的x)
>>>y

可能也很有用。如果您没有听说过,还有字典和集合理解。此外,生成器表达式通常使用较少的内存,因为没有创建中间列表。