生成器表达式VS列表解析
列表解析都是在方括号里面,而生成器表达式在元括号里面,你只要碰到形式,这一步会给你返回一个结果集
生成器表达式不执行for语句,只有当调用next方法的时候才会执行一次。
他们两个的具体问题可以参考列表解析和生成器之间空间和时间的对比通过作为返回值形式,体现出不同的处理方式
>>> [x**2 for x in range(4)] #列表解析生成了一个列表
[0, 1, 4, 9]
>>> (x**2 for x in range(4)) #生成器表达式,它生成一个生成器对象,只有通过调用next()来取值
<generator object <genexpr> at 0xb71465f4>
>>> G=(x**2 for x in range(4)) #生成器表达式每次只求一个值
>>> next(G)
0
>>> next(G)
1
list可以对一个生成器表达式一次性求出结果,其实拓展一下就是可以针对迭代对象。
>>> list(x**2 for x in range(4)) #list相当与把一个生成器对象的值,循环求出来了。
[0, 1, 4, 9]
生成器函数VS生成器表达式
如果仅仅是for上面的迭代,我们一般都可以用一个生成器函数跟生成器表达式来实现。
其实我感觉生成器表达式就相当与生成器函数被赋予了值的情况,因为只有当对一个函数参数赋予了值以后,它才能成为一个对象,在这里是成为一个generator object,但是你发现其实生成器表达式同样也是生成一个generator对象。也就是生成器表达式是生成器函数的一个特例。
>>> def timestwo(x): #等价于上面生成器表达式
... for c in range(x):
... yield c**2
...
>>> G=timestwo(4)
>>> list(G)
[0, 1, 4, 9]
生成器VS内置数据类型
一个生成器对象只能有一个迭代器,(该对象可以通过生成器表达式生成或者对生成器函数指定实参)
内置数据类型可以有多个迭代器
>>> G=(c*4 for c in 'spam') #创建一个generator object
>>> I1=iter(G) #其实我们可以对G直接调用next,但是这里为了比较使用了iter,在这里它实际上是返回自身的一个对象,就是G
>>> next(I1)
'ssss'
>>> I2=iter(G)
>>> next(I2) #值是紧接着上一个iterator后面的字符
'pppp'
>>> string='spam'
>>> s1=iter(string) #创建一个string的迭代对象
>>> next(s1)
's'
>>> s2=iter(string)
>>> next(s2)
's'