一、 补充知识
isinstance(a,A)
True
以上如果返回值为True则表示a是A的一个子类
Iterable是一个类,这个类的子类都是可迭代对象
由上图可以知 列表是可迭代对象
问题来了:是否可以通过自己创建的类产生的对象判断ta可以迭代呢?
发现不可以
如果想让类创建的实例对象用for的话,在类中额外添加方法__iter__
可行但是依旧不可以拿for来循环‘
因为
普通列表在for循环中取第一个完成后内部自动跳到第二个,但是自己定义的类没有这个光标
因此得在iter 返回一个对象的引用(这个引用必须包含iter和next方法)才可以进行for循环
for temp in classmate:
pass
- 当for循坏是否判断可以运行的时候就是判断classmate是否是一个可迭代对象
- 如何判断其是否是一个可迭代对象呢?只要classmate中由iter的这个类就算可迭代对象
- 此时调用对象中iter函数来得到return的返回值,只要返回值中既包含iter和next俩方法,此值就算是迭代器
- 使用迭代器中的next来进行正常可迭代对象的光标下移
- 因此每调用一次for循环的temp的时候j就会调用next返回给temp
第一行代码iter(classmate)返回迭代器,将迭代器给一个变量
第二行代码将返回True时证明其就是迭代器
上两行代码验证其是否是迭代器
协程很简单但是想明白协程得仔细思考
学习迭代器,生成器,yiled(面试 yiled和return有什么区别),greenlet gevent以上
迭代器: 占有极小的内存空间来完成
斐波那契数列:具有后者和等与前两者的和特性的数列
二迭代器的其他用途
不只是for循环可以进行迭代器,类型转换也可以进行迭代器
元组转换列表,新建列表。重新生成list,通过list()的迭代器一个一个加入新的列表
生成器:特殊的迭代器
创建生成器的一种方法:把列表推导式的中括号换成小括号
创建生成器的第二种防范:
def creat_num(all_num):
a,b =0,1
current_num = 0
while current_num < all_num:
print(a)
a,b = b,a+b
current_num +=1
obj = creat_num(10)
上图为斐波那契数列打印结果
根据上图代码加入了yield,当一个函数中有yeild的时候
- 说明他是生成器。就把这个函数当做类看待
- 说明其执行顺序与其他不一样,代码执行到for循环时根据函数从上到下走走到图片中2时即yeild直接打印数值结果,for循环又开始进行第二次循环并不是从头开始而是走到之前yeild暂停的地方继续向下,以后几次循环也只是在while循环中进行
************1.通过next启动生成器启动生成值
上图可以看到,生成器是特殊的迭代器
因此obj = next(obj)这不是调用函数而是创建了生成器对象
同时拿next’来进行下一步,由结果显示next的值就是yield的值
注意:谁让生成器按照next’返回如果想得到本身函数的返回值则在try中写入ret.value,此中的值value保存了return
def creat_num(all_num):
a,b =0,1
current_num = 0
while current_num < all_num:
# print(a)
yield(a)
a,b = b,a+b
current_num +=1
obj = creat_num(10)
while True:
try:
ret = next(obj)
print(ret)
except Exception as ret:
print(ret.value)
break
~
~
**
**********2.通过send来启动生成器去生成值
**
如上图所示,,yield a 传值给next,next负责打出a之后再回到程序的下一句print(。。。)
但是显然如果用yield左边的赋值语句没有走,所以此时send的内容代表了yield a 传值给ret,则ret打印出来的是哈哈哈哈
生成器特色可以让代码暂停进行并且保存值
三、多任务用途协程------生成器
进程浪费资源,线程比进程轻量级,而协程更加方便快捷
import time
def task_1():
while True:
print("-------1----------\n-")
time.sleep(0.6)
yield
def task_2():
while True:
print("--------2-------")
time.sleep(0.1)
yield
def main():
t1 = task_1()
t2 = task_2()
while True:
next(t1)
next(t2)
if __name__ == "__main__":
main()
完成多任务,展示结果如图
四、yield升级版greenlet
五、gevent协程的并发库
gevent是greenlet的升级版
但不同的是,gevent遇到延时会切任务让其继续下去,不卡死。没有延时时按照正常顺序。
但是time.sleep在gevent不可进行不管用得用gevent.sleep或者使用monkey。parch_all()这个补丁使得正常延迟函数可以运行