单个线程内模拟多任务。
1.迭代器Iterable
集合数据类型:字符串、列表、元组、字典,生成器类,带yie的生成器方法,都可以迭代。即都可以for--in--。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
from collections.abc import Iterable from collections.abc import Iterator class MyCoroutine(object): def __init__(self): self.list = list() # 列表 self.pointer = 0 # 元素指针 def addElement(self, ele): # 添加元素 self.list.append(ele) # 重写此方法。类就是可迭代对象 def __iter__(self): return self # 重写此方法。类就可进行迭代操作 def __next__(self): # for循环每执行一次,即更新指针一次 if len(self.list) > self.pointer: ele = self.list[self.pointer] # 根据当前指针提取元素 self.pointer += 1 return ele else: self.pointer = 0 # 复位指针 raise StopIteration # 结束for循环 mc = MyCoroutine() mc.addElement("哈哈") mc.addElement("哈哈2") mc.addElement("哈哈3") mc.addElement("哈哈4") print(isinstance(mc, Iterable)) # True 须重写__iter__ mcIter = iter(mc) # 获取类的迭代器 print(isinstance(mcIter, Iterator)) # True 须重写__next__ # print(next(mcIter)) # 等同于调用 mcIter.__next__() 方法 # 多次next(),当没有可遍历项时,会触发 StopIteration ,须try---except---处理 for element in mc: print(element) # 调用 __next__ 方法 # for-in- 自动处理StopIteration # ######################### 迭代器案例 ########################## class Fibonacci: """斐波那切数列。前两位数是0和1,从第3位开始,值为前两位的和 0 1 1 2 3 5 8 13 """ def __init__(self, step): self.step = step # 到数列第几位 self.element1 = 0 # 第一位 self.element2 = 1 # 第2位 self.pin = 0 # 元素指针 def __iter__(self): return self def __next__(self): if self.pin < self.step: result = self.element1 self.element1, self.element2 = self.element2, self.element1 + self.element2 self.pin += 1 return result else: self.pointer = 0 raise StopIteration fbnc = Fibonacci(10) for value in fbnc: print(value, end="\t") print() |
2.生成器Generator
生成器也是一种迭代器。
创建方式1:
1 2 3 |
# 使用 生成式 创建生成器 tpl = (i+3 for i in range(9)) print(tpl) # <generator object <genexpr> at 0x1036c64f8> 如果是[]列表,则默认生成最终元素 |
创建方式2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# 这段代码块形式上是一个函数 def generateFibonacci(step): a, b = 0, 1 pin = 0 while pin < step: # print("-"*10) # 出现 yield 这个关键字,这段代码块就变成了生成器模板 # yield会返回a,并阻塞代码的执行。当a被使用后,代码继续向下执行 yield a a, b = b, a+b pin += 1 # print("="*10) # 调用 generateFibonacci 这个代码块时,发现yield关键字 # 于是自动根据代码块创建了生成器对象——即一个迭代器 fibonacci = generateFibonacci(10) # 定义生成器时不执行函数内的代码 while True: try: print(next(fibonacci)) # 迭代器方法next。当第一次next时,才开始执行函数内代码,并阻塞在yield处 except StopIteration as e: break fibonacci = generateFibonacci(10) for i in fibonacci: print(i) # i 即生成器中yield返回的a |
向生成器传递参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# 这段代码块形式上是一个函数 def generateFibonacci(step): a, b = 0, 1 pin = 0 while pin < step: # 先执行等号右边 yield阻塞代码执行,将a发给迭代操作 # 然后接收yield操作的结果——send发回的数据,赋给back back = yield a print("back=", back) a, b = b, a+b pin += 1 # 调用 generateFibonacci 这个代码块时,发现yield关键字 # 于是自动根据代码块创建了生成器对象——即一个迭代器 fibonacci = generateFibonacci(10) # 首次操作生成器不可send,因为此时从函数的第一行执行,还没有变量接收数据 # print(fibonacci.send(99)) # TypeError: can't send non-None value to a just-started generator # 或者可以 send(None) print(next(fibonacci)) # 第一次next执行后yield阻塞,还未创建back print(fibonacci.send("Hello yield")) # 再次next-send,yield放开,创建back,并向下执行代码 # 0 。 # 这是yield返回的值 # back= Hello yield # 这是yield接收send的参数后赋给back, # 1 。 # 这是第2次循环,执行到yield,再次返回的值 |
3.yeild实现多任务
协程:多个函数协商轮流执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import time def taskA(): while True: print("任务a---") time.sleep(1) yield # 代码块出现yield,因此这是个生成器模板 def taskB(): while True: print("任务b---") time.sleep(3) yield # 当这个yield执行时,B阻塞,切换到A执行;A的yield执行时再回到B def main(): generatorA = taskA() # 定义一个生成器。一个并发任务 generatorB = taskB() while True: next(generatorA) next(generatorB) if "__main__" == __name__: """这是在同一个线程内不停的切换”函数“, 实现的 伪多任务 """ main() |
4.greenlet实现多任务
使用指令安装 pip3 install greenlet 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import time from greenlet import greenlet def taskA(): while True: print("任务A---") letB.switch() # 切换到taskB time.sleep(1) def taskB(): while True: print("任务B---") letA.switch() # 切换到taskB time.sleep(1) letA = greenlet(taskA) # 创建一个并发任务 letB = greenlet(taskB) letA.switch() # 切换到并执行taskA """在一个线程内切换功能函数 实现‘多任务’ """ |
5.gevent实现多任务
使用指令 pip3 install gevent -i https://pypi.douban.com/simple/ 安装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import gevent from gevent import monkey monkey.patch_all() # 将原生耗时代码替换为gevent自己的耗时代码 def task(name, n, st): for i in range(n): print("任务", name, gevent.getcurrent(), i) gevent.sleep(st) # 当有耗时操作时,自动切换执行其它任务 # sleep耗时操作 比如网络请求、文件读写 task1 = gevent.spawn(task, "A", 4, 3) task2 = gevent.spawn(task, "B", 5, 2) task3 = gevent.spawn(task, "C", 12, 1) # task1.join() # task2.join() # task3.join() gevent.joinall( [task1, task2, task3] ) print("全部任务完成") # 3个任务全部结束后执行 |
-end
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/2667.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设