什么是生成器?
在Python中,一边循环一边计算的机制,称为生成器(generator),可以大大的节省内存空间。
如果得到一个生成器呢?
# 这是列表推导式
list1 = [x for x in range(10)]
print(list1)
而想要得到一个生成器,只要将两边的“[]”换成“()”即可
g = (x*3 for x in range(10))
print(type(g) # <class 'generator'> 得到的类型是生成器
print(g)
#<generator object <genexpr> at 0x000001DF35D5BDD0>
但是当我们想要把生成器里的数字打印出来时,会出现一串内存地址。
如果我们想得到生成器中的数字,我们需要调用它,有两种方法。 1.__next__()方法
print(g.__next__()) # 0
print(g.__next__()) # 3
print(g.__next__()) # 6
2.next()函数
print(next(g)) #9
yield的作用
1. 只要函数中有yield,那么函数就变成了生成器
def func():
n = 0
while True:
n += 1
yield n # yield 相当于将n返回给g + 暂停
g = func()
print(g.__next__())
>>>1
下面来一道实例:生成斐波那契数列。 斐波那契数列指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 这个数列从第3项开始,每一项都等于前两项之和。
def fib(length):
a = 0
b = 1
n = 0
while n < length:
a, b = b, a + b
yield b
n += 1 # 下一次调用从此处开始执行
return "超过次数!"
# 会返回给报错原因stop iteration中 (StopIteration: 超过次数!)
result = fib(8)
print(result.__next__())
print(result.__next__())
print(result.__next__())
print(result.__next__())
print(result.__next__())
# 调用超过length的次数将会报错
打印结果:
1
2
3
5
8
下面我将贴出一个例子,并分析它的执行过程。
#这是原代码
def foo():
n = 0
while True:
temp = yield n
print("temp", temp)
n += 1
# 调用
f = foo()
foo1 = f.send(None)
print("foo1:", foo1)
foo2 = f.send("foo2") #send函数相当于给yield传值
print("foo2:", foo2)
第一轮分析:
在第②步中,代码并不会执行函数的部分,由于函数中yield出现,因此会直接跳到第③步
第二轮:
最后的结果:
foo1: 0
temp foo2
foo2: 1
有一个要注意的地方就是为什么第一次要send(None)呢?* 由于第一次还没有进入到循环中,无法将值传给yield,因此会报错,如下: