迭代 :在原来的基础上扩展得到新的东西
迭代器:怎么判断是否可以迭代?
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 语句 的 函数称为生成器模版
多个生成器对象之间互不影响
迭代器 可能产生的 异常 我们用 异常捕获退出
send 一般用于 在某种情况下,改变条件 send 用于 yield 的结论
但 send 不要第一次启动,会奔溃 ,除非传None
协程的多任务 实现的消耗非常轻量 ,只是通过 yield 直接进去执行。
greenlet类 对 yield 类 进行了 封装
greenlet 通过 switch 进行切换
gevent 是对 yield greenlet的封装
但是 前两者 不是真正意义的并行 sleep() 其他执行流执行不了
但 gevent 对sleep() 延时进行优化 ,只要遇到延时, 将会进行推到有几个 gevent对象 , 再去执行别的gevent对象
协程核心 ; 利用 sleep()的 延时/阻塞 ,去执行别的任务
协程核心 ; 利用 sleep()的 延时/阻塞 , 去执行别的任务
协程核心 ; 利用 sleep()的 延时/阻塞 , 去执行别的任务
遇到 gevent 那么内部所有的阻塞 睡眠都得用 gevent内的方法
最好 打补丁 : monkey.patch_all() 就可以直接将耗时的东西替换成gevent内相应的耗时操作。
原理 就是 编译时进行自动扫描替换了。
回收资源: join 但是重复太多
最好 gevent.joinall([ g1,g2, … ])
GIL 解 将python 的 线程 搞成并发的
这并不是 python 语言的问题: 而是 GIL解释器的问题
原理: 程序并不能直接执行, 这时候需要解释器将程序翻译成CPU认识的01010101
解释器用什么语言实现, 只要能实现翻译就行 。 python官网推荐C解释器 C-python
起因就是 python 之父 吉多 当年没考虑到这个问题