看到吐血 _(´ཀ`」 ∠)_

  • 协程(Coroutine)本质上是一个函数,特点是在代码块中可以将执行权交给其他协程
  • 众所周知,子程序(函数)都是层级调用的,如果在A中调用了B,那么B执行完毕返回后A才能执行完毕。协程与子程序有点类似,但是它在执行过程中可以中断,转而执行其他的协程,在适当的时候再回来继续执行。
  • 协程与多线程相比的最大优势在于:协程是一个线程中执行,没有线程切换的开销
  • 这里用到的是asyncio库(Python 3.7),这个库包含了大部分实现协程的魔法工具
    • 使用 async 修饰词声明异步函数
    • 使用 await 修饰词调用异步函数
    • 使用 asyncio.create_task 创建任务

解析协程运行时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import asyncio
import time

async def a():
print("欢迎使用 a !")
await asyncio.sleep(1)
print("欢迎回到 a !")

async def b():
print("欢迎来到 b !")
await asyncio.sleep(2)
print("欢迎回到 b !")

async def main():
task1 = asyncio.create_task(a())
task2 = asyncio.create_task(b())
print("准备开始")
await task1
print("task1 结束")
await task2
print("task2 结束")

if __name__ == "__main__":
start = time.perf_counter()

asyncio.run(main())

print('花费 {} s'.format(time.perf_counter() - start))

运行结果

  • 解释:
    • 1、asyncio.run(main()),程序进入main()函数,开启事件循环
    • 2、创建任务task1、task2并进入事件循环等待运行
    • 3、输出准备开始
    • 4、执行await task1,用户选择从当前主任务中切出,事件调度器开始调度 a
    • 5、a 开始运行,输出欢迎使用a!,运行到await asyncio.sleep(1),从当前任务切出,事件调度器开始调度 b
    • 6、b 开始运行,输出欢迎来到b!,运行到await asyncio.sleep(2),从当前任务切出
    • 7、以上事件运行时间非常短(毫秒),事件调度器开始暂停调度
    • 8、一秒钟后,a的sleep完成,事件调度器将控制权重新交给a,输出欢迎回到a!,task1完成任务,退出事件循环
    • 9、await task1完成,事件调度器将控制权还给主任务,输出task1结束,然后在await task2处继续等待
    • 10、两秒钟后,b的sleep完成,事件调度器将控制权重新传给 b,输出欢迎回到 b!,task2完成任务,从事件循环中退出
    • 11、事件调度器将控制权交还给主任务,主任务输出task2结束,至此协程任务全部结束,事件循环结束。

异步接口同步实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"""
- 简单爬虫模拟
- 这里用异步接口写了个同步代码
"""

import asyncio
import time

async def crawl_page(url):
print('crawling {}'.format(url))
sleep_time = int(url.split('_')[-1])
await asyncio.sleep(sleep_time) # 休眠
print('OK {}'.format(url))

async def main(urls):
for url in urls:
await crawl_page(url) # await会将程序阻塞在这里,进入被调用的协程函数,执行完毕后再继续


start = time.perf_counter()

# pip install nest-asyncio
asyncio.run(main(['url_1', 'url_2'])) # 协程接口

print("Cost {} s".format(time.perf_counter() - start))

使用Task实现异步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 异步实现

import asyncio
import time

async def crawl_page(url):
print('crawling {}'.format(url))
sleep_time = int(url.split('_')[-1])
await asyncio.sleep(sleep_time)
print('OK {}'.format(url))

async def main(urls):
tasks = [asyncio.create_task(crawl_page(url)) for url in urls]
for task in tasks:
await task
# 14、15行也可以换成这一行await asyncio.gather(*tasks)
# *tasks 解包列表,将列表变成了函数的参数,与之对应的是,** dict 将字典变成了函数的参数

start = time.perf_counter()

asyncio.run(main(['url_1', 'url_2']))

print("Cost {} s".format(time.perf_counter() - start))

公式插入方式

  1. 行内公式可用\(...\)$...$
  • 例如$ f(x)=x^2 $,显示为$ f(x)=x^2 $
  1. 独立公式(单独另起一行,公式会居中),使用$$...$$\[...\]
  • 例如:$$ \limit{f(x)dx} $$
1
2
3
4
5
6
1. 行内公式可用`\(...\)``$...$`
- 例如`$ f(x)=x^2 $`,显示为$ f(x)=x^2 $

2. 独立公式(单独另起一行,公式会居中),使用`$$...$$``\[...\]`
- 例如:`$$ \limit{f(x)dx} $$`
$$ \int_a^b{f(x)dx} $$

MATLAB基本操作

1. 对象定义
使用sym定义单个对象、使用syms定义多个对象

2. 使用limit求极限

1
limit(f,v,a) % 使用limit(f,v,a,'left')可求左极限

3. 导数
使用diff(f,v,n)对$ f(v)=v^{t-1} $求 $ n $ 阶导 $ \frac{d^nf}{d^nv} $,n缺省时,默认为1,diff(f)默认求一阶导数。

4. 定积分和不定积分
使用int(f,v)求f对变量v的不定积分,使用int(f,v,a,b)求f对变量v的定积分,a、b为积分上下标。$ \int{f(v)dv} $、$ \int^{a}_{b}{f(v)dv} $。



博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 , 总访问量为 次 。