python实习总结(yeild,async,azwait和协程)

作者:==今天写代码了吗 时间:2021-06-16 20:40:45 

一、yield使用简析

yield是一个生成器generator,返回一个interable对象。

该对象具有next()方法,可以通过next()查看接下来的元素是什么。

1.interable对象 ,可以遍历的对象,如: list,str,tuple,dict,file,xrange等。

2.yield的作用是什么?只是循环里面的获取中间变量的一个方法,把想要的变量每次使用yield保存起来直至循环结束,循环结束得到了一个generator对象

3.为什么使用yield?使用yield,一个函数改写成generator,便具有了迭代的能力,比起用类的实例保存状态计算下一个需要迭代的值,代码更加简洁,执行流程十分简单。

4.如何判断yield的类型


def fab(max):
   n, a, b = 0, 0, 1
   while n < max:
       yield b      # 使用 yield
       # print b
       a, b = b, a + b
       n = n + 1
for n in fab(5):
   print n

fab不是generator,fab(5)是generator。

好比类的定义和类的实例的区别。


>>>import types
>>> isinstance(fab, types.GeneratorType)
False
>>> isinstance(fab(5), types.GeneratorType)
True

fab 是无法迭代的,而 fab(5) 是可迭代的。


>>>from collections import Iterable
>>> isinstance(fab, Iterable)
False
>>> isinstance(fab(5), Iterable)
True

5.yield在文件读取的应用?

如果字节使用read()读取一个文件,会导致不可预测的内存占用。好的方法是使用yield,固定长度的缓冲区来不断读取文件,生成读文件的迭代的generator。


def read_file(fpath):
   BLOCK_SIZE = 1024
   with open(fpath, 'rb') as f:
       while True:
           block = f.read(BLOCK_SIZE)
           if block:
               yield block
           else:
               return

二、async和await的使用

1.什么是进程、协程、异步?

  • 协程是什么?

一种用户级轻量级的线程,拥有自己的寄存器上下文和栈。

协程切换时候,将寄存器和栈保存在其他地方,当返回的时候,恢复原先保存的寄存器上下文和栈。

  • 为什么使用协程?

主流语言采用多线程并发,线程相关的概念是抢占式多任务,协程相关的协作式多任务。

不管是多进程还是多线程,每次阻塞、切换陷入系统调用。

CPU跑操作系统的调度程序,调度程序决定运行哪一个进程(线程)。

线程非常小心的处理同步问题,而协程完全不存在这个问题。

对于CPU而言,多协程是单线程,CPU不会考虑调度、切换上下文,省去CPU的切换开销。协程好于多线程的原因。

  • 如何使用协程?

多进程+协程下,避开了CPU切换的开销,又能把多个CPU充分利用起来,这种方式对于数据量较大的爬虫还有文件读写之类的效率提升是巨大的。

2.如何处理200W数量的url,把所有的url保存下来?

  • 单进程+单线程

  • 单进程+多线程:开十个线程,速度不能提高十倍。线程的切换是有开销的,无能无限的创建线程。

  • 多进程+多线程:多进程的每个进程占用一个CPU,多线程一定程度上绕过了阻塞时间,所以相比单进程的多线程效率更高。

  • 协程

3.使用async的await和gather

  • await接受一个协程列表,返回done、pending两个列表。done是已经完成的协程,pending是仍在跑的协程。通过.result()获取完成的结果

  • gather以gather(cro1, cro2, cro3, cro4…)的方式接受协程,返回的是一个结合了这么多个任务的协程。

async的使用:https://blog.csdn.net/qq_29785317/article/details/103294235


async def func1(num):
   print('--func1 start--')
   await asyncio.sleep(num)
   print('--func1 done--')
   return 'func1 ok'
async def func2(num):
   print('--func2 start--')
   await asyncio.sleep(num)
   print('--func2 done--')
   return 'func2 ok'
async def main():
   task1 = asyncio.ensure_future(func1(3))
   task2 = asyncio.ensure_future(func2(5))
   tasks = [task1, task2]
   res = await asyncio.gather(*tasks)
   return res
   # done, pending = await asyncio.wait(tasks)
   # for t in done:
   #     print(t.result())
   # print(done)
   # print(pending)
if __name__ == '__main__':
   loop = asyncio.get_event_loop()
   result = loop.run_until_complete(main())
   print(result)
```python
--func1 start--
--func2 start--
--func1 done--
--func2 done--
['func1 ok', 'func2 ok']

三、协程的理解

1.协程的过程

协程中yield是控制流程的方式。

yield同 * 一样,是一个生成器,需要先激活才能使用。


>>> def simple_corotine():
...     print('---->coroutine started')
...     x = yield#有接收值,所以同生成器一样,需要先激活,使用next
...     print('---->coroutine recvied:',x)
...
>>> my_coro = simple_corotine()
>>> my_coro
<generator object simple_corotine at 0x0000000000A8A518>

>>> next(my_coro)#先激活生成器,执行到yield val语句#或者使用send(None)也可以激活生成器
---->coroutine started
>>> my_coro.send(24)#向其中传入值,x = yield
---->coroutine recvied: 24
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration#当生成器执行完毕时会报错

2.协程在运行中的四种状态

GEN_CREATE:等待开始执行

GEN_RUNNING:解释器正在执行,这个状态一般看不到

GEN_SUSPENDED:在yield表达式处暂停

GEN_CLOSED:执行结束


>>> def averager():
...     total = 0.0
...     count = 0
...     aver = None
...     while True:
...             term = yield aver
...             total += term
...             count += 1
...             aver = total/count
...
>>> coro_avg = averager()
>>> coro_avg.send(None)
>>> coro_avg.send(10)
10.0
>>> coro_avg.send(20)
15.0
>>> coro_avg.send(30)
20.0
>>> coro_avg.send(40)
25.0

每次循环结束在yield出暂停,直至下一个参数传进来。

3.预激活协程的装饰器(自定义激活的方式)

@装饰器的作用是什么?装饰原有的函数,给原油函数增加一个新的功能和方式。

为什么@可以实现装饰器的功能?函数也是对象,函数可以作为实参传给掐函数。


>>> def coro_active(func):
...     def inner(*args,**kwargs):
...         gen = func(*args,**kwargs)
...         next(gen)   #gen.send(None)
...         return gen
...     return inner
...
>>> @coro_active
... def averager():
...     total = 0.0
...     count = 0
...     aver = None
...     while True:
...             term = yield aver
...             total += term
...             count += 1
...             aver = total/count
...
>>> coro_avg = averager()
>>> coro_avg.send(10) 10.0 >>> coro_avg.send(20) 15.0 >>> coro_avg.send(30) 20.0

4.终止协程和异常处理

当协程的next函数或者send函数发生错误的时候,协程就会终止掉。

需要创建异常捕捉对协程的异常情况进行处理,关闭当前协程。

5.让协程返回值

yield使用方法 ↩︎

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

来源:https://blog.csdn.net/yue_yue0/article/details/118499351

标签:python,yeild,async,azwait,协程
0
投稿

猜你喜欢

  • 解决mysql的int型主键自增问题

    2024-01-28 11:54:45
  • IE8新特性及IE8安装使用 目录

    2008-04-01 09:50:00
  • oracle数据库中如何处理clob字段方法介绍

    2024-01-17 05:55:41
  • 快速理解MySQL中主键与外键的实例教程

    2024-01-26 16:16:57
  • Python发送邮件封装实现过程详解

    2021-06-13 09:19:41
  • Python技能树共建之python urllib 模块

    2023-02-07 04:02:40
  • MySQL——修改root密码的4种方法(以windows为例)

    2024-01-16 17:50:55
  • Python实现批量翻译的示例代码

    2023-02-27 04:24:12
  • uni-app网络请求、数据缓存实例详解

    2023-08-09 03:49:12
  • Python获取脚本所在目录的正确方法

    2022-12-07 14:37:36
  • Laravel使用Queue队列的技巧汇总

    2024-06-05 09:46:03
  • Java通过数据库表生成实体类详细过程

    2024-01-23 15:39:06
  • MySQL 替换某字段内部分内容的UPDATE语句

    2024-01-22 17:45:49
  • python区块链实现简版工作量证明

    2021-03-21 18:08:22
  • 简单了解python 生成器 列表推导式 生成器表达式

    2023-12-05 09:21:02
  • 在DOS界面如何运行python的py文件

    2022-05-01 16:39:33
  • Django上线部署之IIS的配置方法

    2023-02-18 05:17:52
  • Python统计文件中去重后uuid个数的方法

    2023-07-11 17:20:06
  • Xml Http抓取数据时乱码问题解决

    2008-04-24 11:16:00
  • python中如何使用insert函数

    2023-08-02 17:04:43
  • asp之家 网络编程 m.aspxhome.com