如何识别生成器与列表理解

时间:2013-08-13 14:42:01

标签: python generator list-comprehension generator-expression

我有这个:

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

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

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

6 个答案:

答案 0 :(得分:10)

您正在传递generator expression

list comprehension is specified with square brackets[...])。列表推导首先构建列表对象,因此它使用与列表文字语法密切相关的语法:

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

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

生成器表达式始终使用(...)圆形画面,但当用作调用的 only 参数时,可以省略括号;以下两个表达式是等效的:

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

从生成器表达式文档中引用:

  

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

答案 1 :(得分: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>

你正在传递一个发电机。

答案 2 :(得分:2)

那是一个发电机:

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

列表推导包含在[]

答案 3 :(得分:1)

您可能也会问,&#34;这种语法是否真正导致sum一次使用一个生成器,或者它是否秘密创建了生成器中每个项目的list第一&#34 ;?检查这一点的一种方法是在非常大的范围内尝试并观察内存使用情况:

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

此案例的内存使用情况是不变的,其中range(int(1e8))创建完整列表并消耗数百MB的RAM。

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

def print_it(obj):
    print obj

print_it(i for i in xrange(5))
# prints <generator object <genexpr> at 0x03853C60>

答案 4 :(得分: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和mdscruggs在帖子中解释的内容一致。

答案 5 :(得分:0)

您正在传递生成器对象,列表推导被[]包围。