如何区分生成器和列表推导式

7

我有这样一个东西:

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

我的问题是,在这种情况下,我传递给sum的是列表推导还是生成器对象?我该如何判断?是否有一般规则可以遵循?
同时请记住,sum本身需要一对括号来包围其参数。我认为上面的括号是用于sum而不是用于创建生成器对象的。你同意吗?
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

引用生成器表达式文档:

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


@Martin Pieters 但是请记住,sum本身需要一对括号来包围其参数。我认为上面的括号是用于sum而不是用于创建生成器对象。你同意吗? - Ankur Agarwal
1
@abc:我刚刚在解释这个问题;在那种情况下,生成器周围的括号是可选的 - Martijn Pieters
@Martin Pieters 很好,我现在看到你的更新了。那正是我想问的关键问题。谢谢。 - Ankur Agarwal

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
那是一个生成器:
>>> (i*i for i in xrange(5))
<generator object <genexpr> at 0x01A27A08>
>>>

列表推导式被包含在[]中。

1
你可能还会问:“这种语法是否确实使sum一次一个地消耗生成器,或者它会秘密地先创建一个包含生成器中每个项目的list?” 一种检查方法是在一个非常大的范围内尝试并观察内存使用情况:
sum(i for i in xrange(int(1e8)))

此情况下的内存使用量是恒定的,而 range(int(1e8)) 则会创建完整列表并消耗数百 MB 的内存。
您可以测试括号为可选项:
def print_it(obj):
    print obj

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

非常有用的信息,用于检查内存使用情况以检测列表推导式或生成器表达式。谢谢。 - Ankur Agarwal

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>

这与马丁和mdscruggs在他们的帖子中解释的一致。

0
你正在传递一个生成器对象,列表推导式被[]包围。

但是请记住,sum本身需要一对括号来包围其参数。 我认为上面的括号是为了 sum 而不是为了创建一个生成器对象。 你同意吗? - Ankur Agarwal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接