day03 - 多任务之迭代器、生成器、协程

一、可迭代对象
介绍:可迭代对像一般可以用for循环进行遍历

  • 可迭代对象判断法
from collections import Iterable
l = [11,22,33]
isinstance(l,Iterable)  # 返回布尔型数值
  • 可迭代对象满足的条件
    此对象中必须含有__iter__方法
    二、迭代器
  • 迭代器判断方法
    ①此对象必须具有__iter__方法
    ②__iter__方法的返回值必须是一个具有__iter__和__next__方法的对象,实际上是返回一个迭代器对象。

总结
①迭代器一定是可迭代对象
②可迭代对象不一定是迭代器

class MyIterator(object):
    """自定义的一个迭代器"""
    def __init__(self, mylist):
        self.mylist = mylist
        # current用来记录当前访问到的位置
        self.current = 0

    def __next__(self):
        if self.current < len(self.mylist.items):
            item = self.mylist.items[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration

    def __iter__(self):
        return self      #此对象本身既是可迭代对象,又是迭代器
  • for循环遍历的本质
    每当for循环遍历依次,就会自动调用可迭代对象中的__iter__方法,此方法返回一个迭代器,然后再紧接着自动调用迭代器中的__next__方法,而__next__方法就会将可迭代对象中的值依次返回,每对可迭代对象遍历一次,迭代器中的__next__就将可迭代对象中的值返回一次
    二、生成器
    介绍: 生成器也是一种特殊的迭代器,只不过实现方式不同

  • 实现
    方式一:列表生成式

l = (x**2 for x in range(10))   #此时l就是一个生成器,可以进行for循环遍历或next()函数获取它的值

方式二:简单来说:只要在def中有yield关键字的 就称为 生成器

def fibonacci(all_num):
	a,b = 0,1
	cur_num = 0
	while cur_num < all_num:
		yield a
		a,b = b, a+b
		cur_num += 1

fibo = fibonacci(10)
for i in range(10):
	ret = next(fibo)
	print(ret)


①生成器和迭代器均减少内存,存储的是产生数据的方式,而不是产生数据的结果
②yiled关键字起到暂停生成器函数的程序,当执行next(迭代器名)时,意味着开启迭代器,并将yield 后面的值传递给next(迭代器名),当再次对迭代器对象调用next(迭代器名)函数时,程序将继续从yield后面的程序运行
③只有yield时默认传递值为None

三、多协程
*介绍:*多协程主要是利用协程中的延时时间,来进行其他协程的运行

  • 实现方式
    方式一:yield方式实现
import time

def work1():
    while True:
        print("----work1---")
        yield
        time.sleep(0.5)

def work2():
    while True:
        print("----work2---")
        yield     #延时操作
        time.sleep(0.5)   #延时操作

def main():
    w1 = work1()
    w2 = work2()
    while True:
        next(w1)    # 执行协程w1 遇到yield,暂停协程w1
        next(w2)    #执行协程w2

if __name__ == "__main__":
    main()

方式二:greenlet实现

from greenlet import greenlet
# 首先需要先下载此模块
import time

def test1():
    while True:
        print "---A--"
        # 手动切换到协程test2运行
        gr2.switch()
        time.sleep(0.5)

def test2():
    while True:
        print "---B--"
        #手动切换到test1运行
        gr1.switch()
        time.sleep(0.5)
 
if __name__ == '__main__':
	#创建多协程
	gr1 = greenlet(test1)    
	gr2 = greenlet(test2)
	#首先切换到gr1中运行
	gr1.switch()

方式三:gevent实现

from gevent import monkey
import gevent
import random
import time

monkey.patch_all()    #打补丁
def work1():
    while True:
        print("----work1---")
        time.sleep(random.random())

def work2():
    while True:
        print("----work2---")
        time.sleep(random.random())   

#依次添加协程
g1 = gevent.spawn(coroutine_work, "work1"),
g2 = gevent.spawn(coroutine_work, "work2")
g1.join()
g2.join()
#一次性添加协程
gevent.joinall([
        gevent.spawn(coroutine_work, "work1"),
        gevent.spawn(coroutine_work, "work2")
])


①打补丁的作用是将协程中所有的延时操作替换成以gevent方式进行的延时操作,因为此模块实现的多协程中,延时操作必须要用gevent方式延时(例如:time.sleep(5)–gevent.sleep(5))
②多协程实现的多任务实际是并发,而不是并行,类似于cpython中的多线程实现的多任务

发布了30 篇原创文章 · 获赞 0 · 访问量 281

猜你喜欢

转载自blog.csdn.net/qq_36334897/article/details/104952919