python并发编程(3)新协程asyncio

一、偏函数

当我们向减少函数的参数时,我们可以用functools.partial(函数名,参数)来实现

import functools

def func(a,b,c):
    return a + b + c

new_func = functools.partial(func,1)
result = new_func(2,3)
print(result)

# 输出结果

# 6

问题:设置一个基点(3,4),求点(1,2),(3,4),(5,6),(7,8)离基点的距离顺序的排序

import math

points = [(1,2),(3,4),(5,6),(7,8)]

def distance(point1,point2):
    x1,y1 = point1
    x2,y2 = point2
    return math.hypot(x2 - x1,y2 - y1)

points.sort(key = functools.partial(distance,(3,4)))
print(points)

# 输出结果

# [(3, 4), (1, 2), (5, 6), (7, 8)]

二、协程函数

用async修饰的函数实协程函数,调用这个函数会返回一个协程对象,但不会执行函数体,若想要执行协程对象,有多种方法,第一个是send()方法

async def run1():
    print(1)
    print(2)
    
async def run2():
    print(3)
    print(4)
    
r1 = run1()# 获得一个协程对象
r2 = run2()

r1.send(None)
r2.send(None)

# 输出结果

# 1
# 2
# 报错StopIteration

报错的原因是,send方法会执行到下一个yield,但是协程中并没有,所以这种执行协程的方法不太推荐

三、await关键字与事件循环

  1. 事件循环:可以理解成一个死循环,一个列表里装着待执行的事件,每次遍历这个列表,找出可执行的事件和不可执行的事件,不可执行的事件包括在等待中阻塞的事件和已经完成的事件,遍历多次,直到列表里的事件全部执行完成为止,获取事件循环需要导入asyncio模块。
  2. await后面根一个可等待对象,1例如future,task,协程。作用是等待await后面根的那个对象执行完成之后再往后执行。
import asyncio


async def run1():
    print(1)
    await r2
    print(2)


async def run2():
    print(3)
    print(4)


r1 = run1()
r2 = run2()

eventloop = asyncio.get_event_loop()
eventloop.run_until_complete(r1)

# 输出结果
#
# 1
# 3
# 4
# 2

r1运行,输出1,之后等待r2运行,输出1,2,r2运行完成,事件循环将会再次循环一次,r1继续执行,输出2,再循环一次,检测到事件运行完成,退出循环。

  1. task任务
    由于协程对象不能直接运行,所以run_until_complete()是先将括号中的协程包装成task对象再运行,我们也可以手动获得这个对象。
import asyncio


async def run1():
    print(1)
    await r2
    print(2)


async def run2():
    print(3)
    print(4)


r1 = run1()
r2 = run2()

eventloop = asyncio.get_event_loop()
task = eventloop.create_task(r1)
eventloop.run_until_complete(task)

# 输出结果
# 
# 1
# 3
# 4
# 2

也可以通过task获取协程运行后的结果

print('result = ',task.result())

因为我们定义的协程没有任何返回值,所以输出result = None

  1. 通过回调函数获取返回值。

什么是回调函数?

  • 当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。
  • 打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数
import asyncio


async def run1():
    print(1)
    await r2
    print(2)
    return 'stop'


async def run2():
    print(3)
    print(4)

def callback(future):# 定义回调函数
    print('callback:',future.result())


r1 = run1()
r2 = run2()

eventloop = asyncio.get_event_loop()
task = asyncio.ensure_future(r1) # 获取task对象
task.add_done_callback(callback)# 绑定回调函数
eventloop.run_until_complete(task)

# 输出结果
# 
# 1
# 3
# 4
# 2
# callback: stop

  1. 利用asyncio协程完成并发
import asyncio


async def run():
    print(1)
    await asyncio.sleep(1)
    print(2)
    return 'stop'

tasks = [asyncio.ensure_future(run()),
         asyncio.ensure_future(run()),
         asyncio.ensure_future(run())]
eventloop = asyncio.get_event_loop()
eventloop.run_until_complete(asyncio.wait(tasks))

# 输出结果
#
# 1
# 1
# 1
# 2
# 2
# 2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若能绽放光丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值