"yield的用法"
是对return的而一种替代,函数碰到return就直接返回了,执行到yield返回一个元素,
并使生成器(使用yield的这个函数)暂停,当再次迭代生成器时,会从yield后面继续执行,
直到遇到下一个yield或者函数结束退出。
1.当函数含有yield,这个函数就不再是普通的函数,而是会被系统默认为是一个生成器(特殊的迭代器)
2.执行到yield p, 返回p值以及整个生成器处于暂停的状态,并跳出当前函数,
执行到调用返回值p的语句
3.当再次执行到这个含有yield的生成器函数时,会自动立即执行到上次暂停的位置继续执行,
也就是从yield p这个语句继续执行
4. 因为是生成器,所以要搭配for、while等循环使用,以防止运行到生成器末尾跳出生成器函数,
就不能再yield了。
有时候,为了保证生成器函数永远也不会执行到函数末尾,会用while True: 语句,
这样就会保证只要使用next(),这个生成器就会生成一个值,是处理无穷序列的常见方法。
def fib(n):
count = 0
a,b = 1,1
while count
yield a #f(1)已经在此返回了1,但上下文信息还保存着
a,b = b,a+b #调用f(2)时才第一次执行这部分代码
count = count+1
f = fib(10) #f就是一个迭代器对象
for i in f: #配合for循环使用
print(i)
>>1,1,2,3,5,8,13,21,34,55
如果写成这样:
print(f)
会打印f在内存中的地址
"python中的迭代器和生成器"
这里主要讲语法,底层定义参考"python协程.py"文件
定义迭代器方法:
iter()可以将列表、集合转换为迭代器,迭代器与普通python对象的区别是迭代器有一个next()方法,
每次调用该方法可以返回一个值
I = iter(L)#I为L的迭代器
I.next()#返回1
I.next()#返回2
I.next()#Error:StopIteration
python中的可迭代对象:
"""
1.range迭代器(按照range不是迭代器.py的意思,这个说法不规范)
2.map,zip,filter迭代器
3.字典视图迭代器:D.keys(),D.iterms()
4.文件类型
"""
生成器是惰性迭代器:
惰性加载是说一些数据在使用时才生产出来,而不是初始化时就加载到内存里了。
'协程的定义是,一个可以随时挂起并让出CPU控制权的控制流。'惰性加载在协程中的意义在于,可以
通过将未来的控制流放在next方法中,使得程序暂时让出CPU,在需要时通过send方法转进回来。
生成器定义语法:
方法1:函数内部使用yield,函数就被解释器视为生成器
def gensquare(N):
for i in range(N):
yield i**2#状态挂起,可以恢复到此时的状态
for i in gensquare(5):#使用方法
print(i, end = '')#[0,1,4,9,16]
x = gensquare(2)#x是一个生成对象
next(x)#等同于x.__next__(),返回0
next(x)#等同于x.__next__(),返回1
next(x)#等同于x.__next__(),抛出异常StopIteration
方法2:
小括号进行列表解析
G = (x ** 2 for x in range(3))
#使用小括号可以创建所需结果的生成器generator object
next(G), next(G), next(G)
效果等同于上面例子
#(1)生成器(生成器函数/生成器表达式)是单个迭代对象
G = (x ** 2 for x in range(4))
I1 = iter(G)#这里实际上iter(G) = G
next(I1)#输出0
next(G)#输出1
next(I1)#输出4
#(2)生成器不保留迭代后的结果
gen = (i for i in range(4))
2 in gen #返回True
3 in gen #返回True
1 in gen #返回False,其实检测2时,1已经就不在生成器中