list对象和generator都可用于迭代, 但list对象在迭代之前, 所有元素的值都已经计算好了, 并且保存在内存中, 但时generator对象的元素在需要获取时才会进行计算, 尚未迭代到的元素还不存在, 因此不占用内存. generator对象保存了当前迭代的位置和生成下一个元素的方法, 这种方式被称为 懒惰计算
g = ( x**2 for x in range(10) ) # 生成一个 generator 对象
print(g)
print( list( g ) ) # 使用list()函数, 获取generator的所有元素
print( list( g ) ) # generator是一次性的, 遍历完后, 将不会重新生成序列, 所里这里得到了一个空列表
# generator与其他接受可变参数的函数结合
#这里生产式表达式作为了max()函数的参数, 没有用额外的圆括号, 但单独使用时, 圆括号是必须的
print( max( x**2 for x in range(5) ) )
print( min( x**2 for x in range(5) ) )
print( sum( x**2 for x in range(5) ) )
调用生成函数的时候返回的是一个generator, 而不是直接返回其值
def fib(n):
i,a,b = 0,0,1
while i < n:
yield b
a, b = b, a+b
i += 1
g = fib(5) # g是一个generator,而不是斐波那契序列中第六个元素的值
for f in g:
print(f)
利用generator function 可以实现非常复杂的生成器, 例如下面这个生成函数每次返回杨辉三角的下一行元素
def triangles(n):
k, t = 0, [1]
while k < n:
yield t
t = [1] + [ t[i-1] + t[i] for i in range(1, len(t)) ] + [1]
k += 1
tr = triangles(10)
for t in tr:
print(t)
True
, 则any() 返回True
, 否则返回False
True
的元素后, 就直接返回True
而不需要继续计算后续的值,因而效率比同样的序列用list表示时高, 这有点像短路或运算, 一旦能确定整个表达式的值, 就不评估后续的值.print( any( [0, 0, 0 ] ) ) # any() 与list一起使用 , 0 等于`False`
print( any( (0, 0, 0) ) ) # any() 与tuple一起使用
print( any( [0, 0, 1] ) ) # 1 等于 True
# any() 与 generator结合使用
g = ( char == 't' for char in 'generator')
print( any( g ) ) # any() 与generator一起使用, 省去了 generator expression的圆括号
print('(g中倒数第三个元素的值是True, 后面应该还有两个`False`)')
for char in g : print( char )
all(seq) 函数以一个布尔序列作为参数, 只要序列中有一个值为False
, 则all()返回False
,仅当序列的值
全为 True
时, all()才返回True. 与短路与运算类似, 当遇到一个False
值时, 就可以直接返回False
了
同样的原因, all()与generator结合使用时, 效率比与list结合使用时高.
t = [1,1,1,'0' ] # '0' 被视为 True
print( all(t) )
# 与generator结合使用
g = (x for x in range(-5, 6))
print( all( g ) )
# 由于0被视为False, 因此当计算得到0后, all()就直接返回False了, g中后续的元素还没有取出
for x in g : print(x) # 打印出 g 中后续的元素