简介
生成器是用来创建Python序列的一个对象,可以用它迭代庞大的序列而不需在内存中创建和存储整个序列,因为它仅仅保存了这个序列的推算算法。Python3中range()是标准的一个生成器
主要作用:为迭代器产生数据
创建一个生成器generator
方法一:通过列表生成式改成生成器,只需将列表生成式的“[]”改成“()", 就等于创建了一个生成器generator
L= [i for i in range(10)]#将列表生成式的[]改成(),就创建了一个生成器
print(L)
generator= (i for i in range(10))
print(generator)#打印输出的仅仅是一个内存地址
列表可以通过下标索引直接访问每一个元素,可是生成器保存的仅是一个推算算法,所以不能通过下标索引来访问元素,但我们可以通过__next__()函数来访问生成器的下一个返回值
print(generator.__next__())#>>>0
print(generator.__next__())#>>>1
print(generator.__next__())#>>>2
由上面可以看出生成器只记录当前位置,并且返回下一个值。可以通过__next__()访问下一个元素,但无法访问当前位置已访问过的元素,即无法往回访问,只能一直访问下一个值
方法二:如果推算的算法比较复杂,用列表生成式无法实现时,可以通过修改函数来实现,生成器返回值使用yield语句声明而不是return,但生成器中又有return语句,此时的return语句作用是当生成器出现异常时返回指定的信息
经典案例:斐波那契数列(1, 1, 2, 3, 5, 8, 13, 21, 34, ...)
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
# 这种赋值,先计算等值的右边再赋值给左边,那么 b=1 a+b=1
# 赋值给左边的a和b,那么 a=1, b=1
# 也等同于:
# t = (b, a + b)
# a = t[0]
# b = t[1]
# 另一种写法:a, b互换,b再加上a的值
# temp = b
# b = a + b
# a = temp
n = n + 1
return "done"
fib(10)
将上面的函数需要打印的地方print(xxx)方法修改为:yield xxx 即可变为生成器
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b#yield是返回一个值的意思,而不是打印
a, b = b, a + b
# 这种赋值,先计算等值的右边再赋值给左边,那么 b=1 a+b=1
# 赋值给左边的a和b,那么 a=1, b=1
# 也等同于:
# t = (b, a + b)
# a = t[0]
# b = t[1]
# 另一种写法:a, b互换,b再加上a的值
# temp = b
# b = a + b
# a = temp
n = n + 1
return "done"
print(fib(10))#>>>打印出一串地址即证明fib()已经变成了生成器
f = fib(10)
print(f.__next__())#>>>1
print(f.__next__())#>>>1
print(f.__next__())#>>>2
生成器在执行过程中,遇到yield就会发生中断,并且记录当前位置和返回指定的值,下次又在记录的位置继续执行下去。
如果一个函数定义中包含了yield关键字,那么这个函数就不再是函数了,而是一个生成器