7

我有这个:

>>> sum( i*i for i in xrange(5))

我的问题是,在这种情况下,我是否将列表理解或生成器对象传递给 sum ?我该怎么说?对此有一般规则吗?

还要记住sum 本身需要一对括号来包围它的参数。我认为上面的括号是用于求和而不是用于创建生成器对象。你不同意吗?

4

6 回答 6

12

您正在传入一个生成器表达式

列表推导式用方括号( [...]) 指定。列表推导首先构建一个列表对象,因此它使用与列表文字语法密切相关的语法:

list_literal = [1, 2, 3]
list_comprehension = [i for i in range(4) if i > 0]

另一方面,生成器表达式创建一个迭代器对象。只有在迭代对象时,才会执行包含的循环并生成项目。生成器表达式不保留这些项目;没有正在构建的列表对象。

生成器表达式总是使用(...)圆括号,但是当用作调用的唯一参数时,括号可以省略;以下两个表达式是等价的:

sum((i*i for i in xrange(5)))  # with parenthesis
sum(i*i for i in xrange(5))    # without parenthesis around the generator

引用生成器表达式文档:

只有一个参数的调用可以省略括号。有关详细信息,请参阅呼叫部分。

于 2013-08-13T14:43:38.570 回答
4

列表推导包含在[]

>>> [i*i for i in xrange(5)]  # list comprehension
[0, 1, 4, 9, 16]
>>> (i*i for i in xrange(5))  # generator
<generator object <genexpr> at 0x2cee40>

你正在传递一个生成器。

于 2013-08-13T14:43:40.053 回答
2

那是一个生成器:

>>> (i*i for i in xrange(5))
<generator object <genexpr> at 0x01A27A08>
>>>

列表推导包含在[].

于 2013-08-13T14:44:19.980 回答
1

您可能还会问,“这种语法真的会导致sum一次使用一个生成器,还是会先秘密地list在生成器中创建每个项目的一个”?检查这一点的一种方法是在非常大的范围内尝试它并观察内存使用情况:

sum(i for i in xrange(int(1e8)))

这种情况下的内存使用是恒定的,其中 asrange(int(1e8))创建完整列表并消耗数百 MB 的 RAM。

您可以测试括号是可选的:

def print_it(obj):
    print obj

print_it(i for i in xrange(5))
# prints <generator object <genexpr> at 0x03853C60>
于 2013-08-13T14:54:05.957 回答
1

我试过这个:

#!/usr/bin/env python

    class myclass:

            def __init__(self,arg):
                    self.p = arg
                    print type(self.p)
                    print self.p





    if __name__ == '__main__':

            c = myclass(i*i for i in xrange(5))

这打印:

$ ./genexprorlistcomp.py 
<type 'generator'>
<generator object <genexpr> at 0x7f5344c7cf00>

这与 Martin 和 mdscuggs 在他们的帖子中解释的一致。

于 2013-08-13T14:56:16.447 回答
0

您正在传递一个生成器对象,列表理解被[].

于 2013-08-13T14:43:49.137 回答