一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - python實習總結(yeild,async,azwait和協程)

python實習總結(yeild,async,azwait和協程)

2022-01-19 00:28==今天寫代碼了嗎 Python

今天是Python實習的第一天,熟悉了環境,第一次使用macbook,氛圍還不錯,努力學習新知識,希望本片文章能給你帶來幫助

一、yield使用簡析

yield是一個生成器generator,返回一個interable對象。

該對象具有next()方法,可以通過next()查看接下來的元素是什么。

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

2.yield的作用是什么?只是循環里面的獲取中間變量的一個方法,把想要的變量每次使用yield保存起來直至循環結束,循環結束得到了一個generator對象

3.為什么使用yield?使用yield,一個函數改寫成generator,便具有了迭代的能力,比起用類的實例保存狀態計算下一個需要迭代的值,代碼更加簡潔,執行流程十分簡單。

4.如何判斷yield的類型

?
1
2
3
4
5
6
7
8
9
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。

好比類的定義和類的實例的區別。

?
1
2
3
4
5
>>>import types
>>> isinstance(fab, types.GeneratorType)
False
>>> isinstance(fab(5), types.GeneratorType)
True

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

?
1
2
3
4
5
>>>from collections import Iterable
>>> isinstance(fab, Iterable)
False
>>> isinstance(fab(5), Iterable)
True

5.yield在文件讀取的應用?

如果字節使用read()讀取一個文件,會導致不可預測的內存占用。好的方法是使用yield,固定長度的緩沖區來不斷讀取文件,生成讀文件的迭代的generator。

?
1
2
3
4
5
6
7
8
9
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

?
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
29
30
31
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同接收器一樣,是一個生成器,需要先激活才能使用。

?
1
2
3
4
5
6
7
8
>>> 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>
?
1
2
3
4
5
6
7
>>> 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  #當生成器執行完畢時會報錯

協程在運行中的四種狀態

GEN_CREATE:等待開始執行

GEN_RUNNING:解釋器正在執行,這個狀態一般看不到

GEN_SUSPENDED:在yield表達式處暫停

GEN_CLOSED:執行結束

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> 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.預激活協程的裝飾器(自定義激活的方式)

@裝飾器的作用是什么?裝飾原有的函數,給原油函數增加一個新的功能和方式。

為什么@可以實現裝飾器的功能?函數也是對象,函數可以作為實參傳給掐函數。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> 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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 午夜一区二区免费视频 | 岛国最新资源网站 | 国产图色 | 成人中文字幕在线高清 | 久久精品午夜一区二区福利 | 精品久久久久久亚洲精品 | 欧美最新在线 | 亚洲国产精品免费在线观看 | 亚洲精品国产在线观看 | 岛国a香蕉片不卡在线观看 荡女淫春2古装 | 欧美三级不卡在线观线看高清 | 性姿势女人嗷嗷叫图片 | 天天综合天天综合 | a级片在线观看免费 | 欧美同性gayvidoes | 四虎最新网址在线观看 | 国产伦久视频免费观看视频 | 暖暖的视频完整视频韩国免费 | 娇喘嗯嗯 轻点啊视频福利 九九九九在线精品免费视频 | 亚洲AV久久无码精品九九软件 | 成人曼画| 好姑娘在线视频观看免费 | 色佬头| 99视频在线看观免费 | 无码人妻视频又大又粗欧美 | 肥胖女性大bbbbbb视频女厕 | 日韩欧美国产一区 | 色综合久久夜色精品国产 | 无颜之月5集全免费看无删除 | 国内精品露脸在线视频播放 | 美女mm131爽爽爽久久 | 久久黄色小视频 | 国产女主播福利在线 | 国内精品在线播放 | 奇米影视777最新在线 | 日韩去日本高清在线 | 日韩欧美综合在线二区三区 | luanlun绝对真实乱 | 欧美xxxxx69| 亚洲精品免费在线 | 桃花岛在线 |