Python学习的第三十九天总结:生成器与协程

今日知识

函数复习,生成器函数复习,协程入门,协程VS多线程,协程版生产者消费者模型

函数的复习

函数的定义与调用

在不执行代码的情况下

需要明确代码是如何一步一步执行的

def func():
    print(1)
    return 2
    print(2)


res = func()
print(res)

生成器函数复习

把return换为yield

函数就会变为一个生成器

只要函数中有了yield,那么这个函数就是生成器函数

对象的创建 = 类名()

生成器的创建 = 生成器函数名()

希望让生成器对象执行起来

生成器对象.__next__()

生成器对象运行起来后

它会执行函数内部的代码

直到遇见yield就会停住

返回yield后面的数据

并且指针状态会停留在yield这一行的行未

当第二次执行

生成器对象.__next__()

从上一次停留的地方继续往下走

情况1,直到遇见yield就会停住,返回yield后面的数据

情况2,没有遇到yield,函数结束,它会按照迭代器协议报错。得不到数据,经协过的代码仍会被执行.

测试代码

def func():
    print(1)
    yield 2
    print(22)


res = func()
print(res)
n = res.__next__()
print(n)

n = res.__next__()
print(n)


# for i in res:
#     print(i)

另一种方式让生成器函数跑起来

方式一

生成器对象.__next__()

方式二

next(生成器对象)

def func():
    print(1)
    yield 2
    print(22)


res = func()
n = next(res)
print(n)

n = next(res)
print(n)

generator
英 [ˈdʒenəreɪtə®] 美 [ˈdʒenəreɪtər]
n.
发电机;发生器;电力公司

iter函数

下面两种情况是一样的效果

iter_obj = res.__iter__()
iter2_obj = iter(res)

效果有点像

li = [1,2,3]

li.sort()
sorted(li)

协程

生成器的进阶

复习函数生成器的特点

关注函数内的代码什么时候会被执行

使用yield协程计算大量的数据

由于两个生成器对象是切换占用cpu,执行任务

不会发生同一时刻抢的情况

因此不用加锁,不存在数据的混乱

当前执行,使用了一个进程,一个主线程来完成的

import time

isum = 0

def addnum():
    global isum
    for i in range(10000000):
        isum += 1
        yield isum

g1 = addnum()
g2 = addnum()

start_time = time.time()
for i in range(10000000):
    next(g1)
    next(g2)

print(isum)
end_time = time.time()
cost_time = end_time - start_time
print('花费了%.f秒' % cost_time)

对比通过多线程来计算,不加锁的情况

结果,多线程完败协程

多线程执行同样代码,耗时11秒,协程砂时4秒

import time

isum = 0

def addnum():
    global isum
    for i in range(10000000):
        isum += 1
        yield isum

g1 = addnum()
g2 = addnum()

start_time = time.time()
for i in range(10000000):
    next(g1)
    next(g2)

print(isum)
end_time = time.time()
cost_time = end_time - start_time
print('花费了%.f秒' % cost_time)

进程线程协程

进程,分配资源的单位

进程中必定有一个主线程

线程,是执行任务的单位

协程,它在线程之内。我们利用了生成器它可以保存状态,可以暂停可以恢复。人为行设计出来的一种多任务的模式。

进程包含线程,线程包含协程。

协程的应用

生产者消费者模型,两个版本

关注切换的主动权在谁

你拍一我拍一双人共同玩游戏

生成器send方法

greenlet提高切换效率

yield会返回

用greenlet对象直接通过switch方法切换到另一函数中

greenlet的用法

导入模式

import greenlet

greenlet
一种绿色小鸟

创建对象

对象 = greenlet.greenlet(test1)

运行

对象.switch()

switch
英 [swɪtʃ] 美 [swɪtʃ]
n.
(电路的)开关,闸,转换器;(尤指突然彻底的)改变,转变;(铁路的)转辙器,道岔
v.
(使)改变,转变,突变;交换;掉换;转换;对调;调班;临时掉换工作时间

明确,为什么要多任务

原因

不想等

真正开发的过程中

不能够明确什么时候要等,什么时候要等多久

a 烧水 15 1 1

b 煮汤 30 1 1

c 挂机 1h 1 1

gevent

event
英 [ɪˈvent] 美 [ɪˈvent]
n.
发生的事情;(尤指)重要事情,大事;公开活动;社交场合;(体育运动的)比赛项目

导入模块

import gevent

创建对象

对象 = gevent.spawn(函数名)

spawn
英 [spɔːn] 美 [spɔːn]
v.
产卵;引发;引起;导致;造成
n.
(鱼、蛙等的)卵

运行

对象.join() 

当gevent对象遇到join方法的阻塞时,就会自动去gevent对象中去看

有没有可以执行的代码

查询范围是所有的对象,不仅仅是只查自己对应的函数的代码

导入猴子

from gevent import monkey
monkey.patch_all()

gevent对象不能够识别常见的一些耗时操作

因此需要猴子来打一个补丁

注意,只能使用from…import来导入

不可以通过gevent.monkey.patch_all()调这个函数

monkey
英 [ˈmʌŋki] 美 [ˈmʌŋki]
n.
猴子;顽皮的孩子;调皮鬼;捣蛋鬼;500英镑
第三人称单数: monkeys 复数: monkeys 现在分词: monkeying 过去式: monkeyed 过去分词: monkeyed

patch
英 [pætʃ] 美 [pætʃ]
n.
色斑;斑点;(与周围不同的)小块,小片;补丁;补块;眼罩
v.
打补丁;缝补;修补
第三人称单数: patches 复数: patches 现在分词: patching 过去式: patched 过去分词: patched
CET4考研TOEFLT

all
英 [ɔːl] 美 [ɔːl]
det.
所有;全部;全体;一切;(与单数名词连用,表示某事在某段时间内持续发生)全部的,整个的
pron.
所有;全部;全体;一切;唯一的事物;所有的事物
adv.
完全;很;十分;非常;太;过分

select

select模块的使用:
select会监听socket或者文件描述符的I/O状态变化,并返回变化的socket或者文件描述符对象

select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)

这是Python select方法的原型,接收4个参数

  1. rlist:list类型,监听其中的socket或者文件描述符是否变为可读状态,返回那些可读的socket或者文件描述符组成的list
  2. wlist:list类型,监听其中的socket或者文件描述符是否变为可写状态,返回那些可写的socket或者文件描述符组成的list
  3. xlist:list类型,监听其中的socket或者文件描述符是否出错,返回那些出错的socket或者文件描述符组成的list
  4. timeout:设置select的超时时间,设置为None代表永远不会超时,即阻塞。

注意:

Python的select方法在Windows和Linux环境下的表现是不一样的,Windows下它只支持socket对象,不支持文件描述符(file descriptions),而Linux两者都支持。

我们可以通过打印来查看select模块提供的作用,返回的rlist,wlist只会返回有改变的监听对象,如果没有改变的函数,那么整个程序会阻塞住

如果我们想要加入新的连接,那么我们只需要把连接对象放进rlist即可,当有数据过来的时候,那么连接就会发生改变(文件描述符),select函数就会帮我们监听到

如果我们想发送数据,那么我们可以把conn加入到wlist,因为发送数据需要我们去输出流数据,然后等待select把wlist里面的消息取出来,我们就可以发送数据了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值