我有这样一个东西:
>>> sum( i*i for i in xrange(5))
我的问题是,在这种情况下,我传递给sum的是列表推导还是生成器对象?我该如何判断?是否有一般规则可以遵循?
同时请记住,sum本身需要一对括号来包围其参数。我认为上面的括号是用于sum而不是用于创建生成器对象的。你同意吗?
我有这样一个东西:
>>> sum( i*i for i in xrange(5))
[...]
)指定。列表推导式首先构建一个列表对象,因此它的语法与列表文字语法密切相关: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
引用生成器表达式文档:
当只有一个参数的调用时,括号可以省略。有关详细信息,请参见调用部分。
列表推导式被放在[]
中:
>>> [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>
您正在传递一个生成器。
>>> (i*i for i in xrange(5))
<generator object <genexpr> at 0x01A27A08>
>>>
[]
中。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>
#!/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>
[]
包围。sum
而不是为了创建一个生成器对象。 你同意吗? - Ankur Agarwal