本文共 2097 字,大约阅读时间需要 6 分钟。
from collections import Iterable# 模拟取款def cash_atm(totalmoney): while totalmoney>0: print("=======(可取金额:%s )=======" % totalmoney) totalmoney -= 100 yield 100 print("=======( 余额:%s )=======" % totalmoney)atm = cash_atm(1000)# 查看atm是个啥,是一个generatorprint(type(atm))# 判断atm是否可迭代print(isinstance(atm, Iterable))# 获取100现金print(atm.__next__())# 消费金额print("买了本书把钱花完了...")# 我想去买个礼物给女朋友,可没有钱了再去取钱print(atm.__next__())'''定义:如果一个函数返回的是一个迭代器,那么这个函数就是生成器那么如果一个函数要返回一个迭代器则需要使用yield语法,该函数就可以返回一个迭代器'''
分析:上面的cash_atm是一个生成器,它调用时返回一个迭代器,根据迭代器的特性,我们只能往下走,不能往回退,上面比较特殊的地方就是:每次请求执行atm的next时,都能够从上一次后面继续往下走,而这个关键在于yield语法,yield是能够跳出当前函数,并且保存执行的状态,下一次调用next时,可以从保存状态继续往下走。
应用分析:
这个生成器有什么应用场景呢?比如说:如果一个操作需要花费很长时间,如果是串行执行的,那么就必须等待操作执行完才可以去干其他的事情,那么这段时间内,你就处于被阻塞状态的,这是不理想的状态。最好的状态是什么呢?比如说我调用接口a,这个接口需要花费一段时间。最好的效果呢就是,我调用该接口,然后去做其他的事,一旦这个接口处理完成后通知我,我来处理这个结果返回的后续操作。这个就是异步操作,相当于我开一个线程去处理接口,接口处理完后会通知主线程处理。场景应用:
模拟异步场景: 有一个餐馆,有一个厨师,有2名食客,食客点包子,厨师做包子,厨师做完后,食客开始吃。这是一个生产消费模型,实现一个单线程的异步效果?实现代码如下:
import time# 生产者消费者模型:厨师生产者,食客消费者# 消费者def consumer(name): print("服务员给我[%s]上包子..."%name) while True: bz = yield print("%s,你好!包子[%s]来了!"%(name,bz))# 生产者def producer(name): c = consumer('A') c2 = consumer('B') c.__next__() c2.__next__() print("厨师[%s]开始做包子了..."%name) for i in range(10): time.sleep(1) print("我[%s]做好两个包子!"%name) c.send(i) c2.send(i)producer('ckmike')
总结:
上面的代码是一个简单的单线程异步效果。生成器的作用非常大。消费者不需要等生产者把所有都准备好就可以把现有的消息消费掉,消费者只是接受消息信息号,把当前的信息处理掉,而生产者负责生成消息,并且信号发送给消费者。上面的效果可能我们还是有点模糊生成器有啥用。比如说现在我要获取一个斐波那契数列。我们没有必要把所有的值一次性加载到内存中,我们可以要一个拿一个(通过生成式实现),概念:这种一边循环一边计算的机制,称为生成器:generator。,与Linux下的cat命令类似,你不需要把大文件一次性加载到内存中,你只要获取部分到内存中,这样大大节省了内存。菲波那切数列实现:# 菲波那切数列def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done'f=fib(10)print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())print(f.__next__())
转载于:https://blog.51cto.com/4837471/2286754