python高级编程语法——多任务:协程(三)

在开始介绍协程之前,咱们先了解一下迭代器和生成器,因为要学习协程,这两部分更是关键。
迭代:是访问集合元素的一种方法,迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往前不能后退。

我们可以对list,tuple,str等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。

如何判断是否可以迭代:
from collections import Iterable
isinstance(数据,Iterable)
如果返回值为True,则表示可以迭代。

迭代器:存储的是生成数据的方式,而不是已经生成的数据。

  for temp in xxx_obj:
      pass
  1. 判断xxx_obj是否可以迭代
  2. 在第1步成立的前提下,调用iter函数,得到xxx_obj对象的__iter__方法的返回值
  3. __iter__方法的返回值 是一个迭代器
  
 判断对象iterator是否是迭代器:
     from collections import Iterator
     iterator = iter(函数名)
     isinstance(iterator,Iterator)
     如果返回值为True,则表示对象是迭代器。

迭代器的优点:能够实现for循环,能够取里面的数据,里面存储的是生成数据的方式。而且不会占用太多的内存。
就好比python2中的range和xrange,range返回的是数据本身,xrange返回的是一个可迭代对象,python3中range也可以当成xrange用。

生成器:是一种特殊的迭代器。
创建生成器的方法:
1. nums = (x*2 for x in range(20)) # 返回的是一个可迭代对象,里面是生成数据的方法,节省空间,就是将列表的中括号变成小括号,可用for循环
2. 在函数中使用yield,那么这个函数则认为不再是函数,而是一个生成器模板,这是调用这个函数创建对象的时候,不再是调用函数,而是创建一个生成器对象。

制作一个简单的生成器案例:

def create_num(all_num):
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        # print(a)
        yield a   # 如果一个函数中有yield语句,那么这个就是在是函数,而是一个生成器模板
        a, b = b, a+b
        current_num += 1   # 如果在调用create_num的时候,发现这个函数中有yield,那么此时,不是调用函数,而是创建一个生成器对象
    obj = create_num(10)
    obj2 = create_num(20)

以上就是迭代器和生成器的大致内容,而在以后的python编程中,使用最多的却是协程:gevent。
首先我们需要在电脑上安装gevent

$ pip3 install gevent

如果你没有权限,就在前面加上一个sudo就可以正确安装了。
安装好了之后,咱们就可以正常使用了。
gevent的使用:

import gevent
def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

g1.join()
g2.join()
g3.join()

这个就是gevent的简单使用,通过运行结果可以知道,它是一个单线程,而这个也是协程的一大优点,因为它既是一个单线程,但也可以实现多任务,它在资源调度的过程中,利用了其他协程中延时的空隙去执行其他的协程。
gevent实现多任务:

import gevent
def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        gevent.sleep(0.5)
        
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

g1.join()
g2.join()
g3.join()

因为gevent是一个封装好了的模块,里面有自己的延时命令,如果以后碰到了其他的延时命令,比如:

time.sleep(0.5)

这时候,这个延时命令并没有执行,需要给这段程序加个补丁:

import gevent
import time
from gevent import monkey

monkey.patch_all()
def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)
        
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

g1.join()
g2.join()
g3.join()

monkey.patch_all()这句代码会将里面的time.sleep()自动转化为gevent.sleep()命令,从而实现延时。

如果在开发过程中,需要执行的协程数量过大,我们可以通过更加简便的代码进行:

import gevent
import time
from gevent import monkey

monkey.patch_all()
def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)
 
g = [g1,g2,g3]
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)

gevent.joinall(g)

这就是协程在开发过程中最后的模板。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值