python 多任务.(协程)

迭代器

生成器

协程 greenlet

协程 gevent

协程 yeild

迭代器

迭代 :在原来的基础上扩展得到新的东西

迭代器:怎么判断是否可以迭代?

from collection import Iterater

isinstance([, ,], Iterable) 进行判断

普通的类不能迭代 ,需要实现魔法方法: __iter__方法 和 next 方法

迭代器原理就是: 需要保存下一个迭代的位置, 那么我们就得模拟实现这个功能

原理 : 魔法方法:创建对象时自动调用魔法方法
B()保存下一个位置的迭代器 ,和当前对象

 class A(object) :
 	def __init__(self):
 		slef.names = list()
 	def add(self, name):
 		self.name.append(names)
	def __iter__():#只要定义就是可迭代的,但不是真正可迭代
 		return  B(self)#由于 要迭代下一个

class B(object):
	def __init__(self, obj)#obj是A类的实例对象 self是自己
		self.obj = obj
		self.count =0
	def __iter__():
		pass;
	def __next__():#魔法方法没有返回值,返回值为None
		if count < len(self.obj.names):
			ret = self.obj.names[self.name[count]]
			count +=1
			return ret
		else:			#那我们自定义抛出一个异常
			raise StopIteration

以上实现比较绕: 对一个学C++的人认为: A对象并没有实例化完成,那么他传递给 B对象怎么调用B对象? 不就无限递归了吗?

 class A(object) :
 	def __init__(self):
 		slef.names = list()
 		self.count =0
 		
 	def add(self, name):
 		self.name.append(names)
 		
	def __iter__(self):	#只要定义就是可迭代的,但不是真正可迭代
 		return self		返回None
 	
	#这里相当于将 __iter__  完全交给 __next__处理了
 	def __next__(self):		#魔法方法没有返回值,返回值为None
		if count < len(self.names):
			ret = self.names[self.count]
			count += 1
			return ret
		else:			#那我们自定义抛出一个异常
			raise StopIteration

a = A ()
迭代器: A_iter = iter(A)
那么以后 下一个: next(a) 该方法自动调用__next__() 并返回__iter__()即当前的值

迭代器比返回列表更节省空间 :从 例如 range() 和 xrange()

生成器

生成器是 特殊的迭代器

例如: 列表/元组推导式 a = (x*2 for i in range(10)) :生成器

含有yield 语句 的 函数称为生成器模版

python 多任务.(协程)_第1张图片
python 多任务.(协程)_第2张图片

多个生成器对象之间互不影响

迭代器 可能产生的 异常 我们用 异常捕获退出

python 多任务.(协程)_第3张图片
python 多任务.(协程)_第4张图片

结论 send 也能调用生成器
	send  一般用于 在某种情况下,改变条件    send	用于 yield  的结论

但 send 不要第一次启动,会奔溃 ,除非传None

使用 yield 实现多任务

协程


python 多任务.(协程)_第5张图片

协程的多任务 实现的消耗非常轻量 ,只是通过 yield 直接进去执行。

greenlet 替换 yield 实现原理还是yield

greenlet类 对 yield 类 进行了 封装

greenlet 通过 switch 进行切换

协程 最实用的—gevent

gevent 是对 yield greenlet的封装
但是 前两者 不是真正意义的并行 sleep() 其他执行流执行不了

但 gevent 对sleep() 延时进行优化 ,只要遇到延时, 将会进行推到有几个 gevent对象 , 再去执行别的gevent对象

协程核心 ; 利用 sleep()的 延时/阻塞 ,去执行别的任务
协程核心 ; 利用 sleep()的 延时/阻塞 , 去执行别的任务
协程核心 ; 利用 sleep()的 延时/阻塞 , 去执行别的任务

遇到 gevent 那么内部所有的阻塞 睡眠都得用 gevent内的方法

最好 打补丁 : monkey.patch_all() 就可以直接将耗时的东西替换成gevent内相应的耗时操作。

原理 就是 编译时进行自动扫描替换了。

回收资源: join 但是重复太多

最好 gevent.joinall([ g1,g2, … ])

解释器 :全局解释器

GIL 保证同一时间只用一个线程执行

C语言的解释器: 多进程效率比多线程高

GIL 解 将python 的 线程 搞成并发的

这并不是 python 语言的问题: 而是 GIL解释器的问题

原理: 程序并不能直接执行, 这时候需要解释器将程序翻译成CPU认识的01010101

解释器用什么语言实现, 只要能实现翻译就行 。 python官网推荐C解释器 C-python

起因就是 python 之父 吉多 当年没考虑到这个问题

你可能感兴趣的:(python)