Python 技能提升(三)

global 和 nonlocal

b = '全局變量 global variable'def foo():a = '局部變量 local variable'# 在局部里面操作全局變量,需要加上聲明global bb = b + '!!!'print(b)foo()
# 全局變量 global variable!!!
b = '全局變量 global variable'def foo():a = '局部變量 local variable'# 在二級局部變量里面操作一級局部變量,則使用 nonlocal 進行聲明def inner_foo():nonlocal aa = a + '!!!'print(a)inner_foo()print(a)foo()
# 局部變量 local variable!!!
# 局部變量 local variable!!!

協程

概念

基本認識

  • 協程不是計算機提供的,它由程序員認為創造
  • 協程(Coroutine),也可以被稱為微線程,是一種用戶態內的上下文切換技術
  • 簡單來說,就是通過一個線程實現代碼塊相互切換執行

實現協程的方式

  • 通過第三方模塊 greenlet
  • yield 關鍵字
  • asyncio 裝飾器(Python 3.4)
  • async、await 關鍵字(Python 3.5)【推薦】

實現

通過 greenlet 實現(了解)

pip install greenlet
from greenlet import greenletdef func1():print(1)		# 第2步:輸出1gr2.switch()	# 第3步:切換到 func2 函數print(2)		# 第6步:輸出2gr2.switch()	# 第7步:切換到 func2 函數,從上一次執行的位置繼續向后執行def func2():print(3)		# 第4步:輸出 3gr1.switch()	# 第5步:切換到 func1 函數,從上一次執行的位置繼續向后執行print(4)		# 第8步:輸出4gr1 = greenlet(func1)
gr2 = greenlet(func2)gr1.switch()  # 第1步:去執行 func1 函數

通過 yield 關鍵字(了解)

def func1():yield 1yield from func2()yield 2def func2():yield 3yield 4# 調用生成器函數,返回生成器對象
obj = func1()
print(obj)# for...in... 背后會不斷調用 next(obj) 來獲取 yield 產生的數據
for i in obj:print(i)# <generator object func1 at 0x0000025CB2A84E80>
# 1
# 3
# 4
# 2"""
從上面的輸出結果來看,我們通過 yield 實現了協程:先在func1中輸出1,然后切換到func2中輸出3,
接著繼續輸出4,最后又切換到func1中輸出2
"""

通過 asyncio 模塊(了解)

  • 在 Python 3.4 版本中引入了 asyncio 模塊
import asyncio@asyncio.coroutine
def func1():print('正在發送請求下載圖片A')yield from asyncio.sleep(2)  # 遇到IO耗時操作,自動切換到task_list中的其他任務print('圖片A下載完成')@asyncio.coroutine
def func2():print('正在發送請求下載圖片B')yield from asyncio.sleep(2)  # 遇到IO耗時操作,自動切換到task_list中的其他任務print('圖片B下載完成')task_list = [asyncio.ensure_future(func1()),asyncio.ensure_future(func2()),
]# 創建一個事件循環對象
loop = asyncio.get_event_loop()# 讓事件循環對象,執行"任務列表"里面的任務
loop.run_until_complete(asyncio.wait(task_list))

通過 async 和 await 關鍵字(掌握)

  • 在 Python 3.5 版本中引入了 asyncawait 關鍵字
import asyncioasync def func1():print('正在發送請求下載圖片A')await asyncio.sleep(3)  # 遇到IO耗時操作,自動切換到task_list中的其他任務print('圖片A下載完成')async def func2():print('正在發送請求下載圖片B')await asyncio.sleep(1)  # 遇到IO耗時操作,自動切換到task_list中的其他任務print('圖片B下載完成')task_list = [asyncio.ensure_future(func1()),asyncio.ensure_future(func2()),
]loop = asyncio.get_event_loop()  # 創建一個事件循環對象
loop.run_until_complete(asyncio.wait(task_list))  # 讓事件循環對象,執行"任務列表"里面的任務
# 在 Python 3.7 版本中,可以使用 asyncio.run() 來替代上面兩行代碼# 運行結果:
# 正在發送請求下載圖片A
# 正在發送請求下載圖片B
# 圖片B下載完成
# 圖片A下載完成

協程函數與協程對象

import asyncio
import time# 協程函數
async def func():print('執行中...')await asyncio.sleep(3)print('執行完畢!')# 協程對象
obj = func()  # 注意:在創建協程對象時,函數內部代碼不會執行# 執行協程函數
# loop = asyncio.get_event_loop()  # 創建一個事件循環對象
# loop.run_until_complete(obj)     # 讓事件循環對象做一些任務
asyncio.run(obj)  # 此行代碼可以替代上面兩行代碼

await

# await + 可等待對象(協程對象、Future對象、Task對象)import asyncioasync def foo1():print('開始執行 foo1 內部代碼')# 遇到IO操作時,掛起當前協程(任務),等IO操作完成之后再繼續往下執行# 當協程掛起時,事件循環可以去執行其他協程(任務)response = await foo2()print('IO請求結束,結果為', response)print('結束執行 foo1 內部代碼')async def foo2():print('Start foo2')await asyncio.sleep(2)print('End foo2')return 'OK'asyncio.run(foo1())# 開始執行 foo1 內部代碼
# Start foo2
# End foo2
# IO請求結束,結果為 OK
# 結束執行 foo1 內部代碼
import asyncioasync def foo1():print('開始執行 foo1 內部代碼')response = await foo2()print('IO請求結束,結果為', response)response = await foo2()print('IO請求結束,結果為', response)print('結束執行 foo1 內部代碼')async def foo2():print('Start foo2')await asyncio.sleep(2)print('End foo2')return 'OK'asyncio.run(foo1())# 開始執行 foo1 內部代碼
# Start foo2
# End foo2
# IO請求結束,結果為 OK
# Start foo2
# End foo2
# IO請求結束,結果為 OK
# 結束執行 foo1 內部代碼

task 對象

  • 用于在事件循環中添加多個任務的
import asyncioasync def foo2(name: str):print(f'{name}開始執行')await asyncio.sleep(2)print(f'{name}結束執行')return f'{name} OK'async def foo1():print('foo1 開始')# 創建task對象,將當前執行func函數任務添加到事件循環中task1 = asyncio.create_task(foo2('task_1'))# 創建task對象,將當前執行func函數任務添加到事件循環中task2 = asyncio.create_task(foo2('task_2'))response1 = await task1print(response1)response2 = await task2print(response2)print('foo1 結束')asyncio.run(foo1())  # 通過協程函數創建一個協程對象,充當參數傳入asyncio.run()函數中# foo1 開始
# task_1開始執行
# task_2開始執行
# task_1結束執行
# task_2結束執行
# task_1 OK
# task_2 OK
# foo1 結束
import asyncioasync def foo2(name: str):print(f'{name}開始執行')await asyncio.sleep(2)print(f'{name}結束執行')return f'{name} OK'async def foo1():print('foo1 開始')task_list = [asyncio.create_task(foo2('task_1')),asyncio.create_task(foo2('task_2')),]return_value, pending = await asyncio.wait(task_list, timeout=2)  # 默認 timeout=None。如果超時,pending里面會有一個"待處理的任務"對象print(return_value)  # 返回一個集合print(pending)  # 返回一個集合print('foo1 結束')asyncio.run(foo1())

future 對象

  • task 繼承 future,task 對象內部 await 結果的處理基于 future 對象來的
import asyncioasync def set_after(future):await asyncio.sleep(2)future.set_result('666')async def main():# 獲取當前事件循環loop = asyncio.get_running_loop()# 創建一個任務(future對象),這個任務什么都不干future = loop.create_future()# 創建一個任務(task對象),綁定了set_after函數,函數內部在2s之后,會給future賦值# 即:手動設置future任務的最終結果,那么future就可以結束了await loop.create_task(set_after(future))# 等待任務最終結果,沒有結果會一直等待下去data = await futureprint(data)  # 666asyncio.run(main())

異步迭代器

import asyncio
import randomclass Reader(object):"""自定義異步迭代器"""def __init__(self):self.count = 0def __aiter__(self):return selfasync def readline(self):await asyncio.sleep(random.randint(1, 5))self.count += 1if self.count == 100:return Nonereturn self.countasync def __anext__(self):val = await self.readline()if val is None:raise StopAsyncIterationreturn valasync def func():obj = Reader()async for i in obj:  # 背后會不斷的調用 __anext__() 方法print(i)asyncio.run(func())

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21277.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21277.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21277.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python 遞歸函數一例

現有示例數據 # 示例數據 pending_join [ {increment: "department Finance", statement_index: 0}, {increment: "name Lisa", statement_index: 2}, {increment: "gender Female", statement_index: 3}, {increment: "hire_date <…

redis如何實現分布式鎖

Redisson是怎么實現分布式鎖的 分布式鎖&#xff1a;Redisson 提供了一種簡單而強大的方式來實現分布式鎖。 它支持多種鎖模式&#xff0c;如公平鎖、可重入鎖、讀寫鎖等&#xff0c;并且提供了鎖的超時設置和自動釋放功能。 鎖的獲取 在Redisson中常見獲取鎖的方式有 lock() …

【代碼隨想錄訓練營】【Day 37】【貪心-4】| Leetcode 840, 406, 452

【代碼隨想錄訓練營】【Day 37】【貪心-4】| Leetcode 840, 406, 452 需強化知識點 python list sort的高階用法&#xff0c;兩個key&#xff0c;另一種逆序寫法python list insert的用法 題目 860. 檸檬水找零 思路&#xff1a;注意 20 塊找零&#xff0c;可以找3張5塊升…

Mysql基礎教程(13):GROUP BY

MySQL GROUP BY 【 GROUP BY】 子句用于將結果集根據指定的字段或者表達式進行分組。 有時候&#xff0c;我們需要將結果集按照某個維度進行匯總。這在統計數據的時候經常用到&#xff0c;考慮以下的場景&#xff1a; 按班級求取平均成績。按學生匯總某個人的總分。按年或者…

“世界酒中國菜”系列活動如何助推鄉村振興和文化交流?

"世界酒中國菜"系列活動如何助推鄉村振興和文化交流&#xff1f; 《經濟參考報》&#xff08;2024年5月24日 第6版&#xff09; 新華社北京&#xff08;記者 張曉明&#xff09; “世界酒中國菜”系列活動自啟動以來&#xff0c;已在國內外產生了廣泛影響。這一國家…

mysql面試之分庫分表總結

文章目錄 1.為什么要分庫分表2.分庫分表有哪些中間件&#xff0c;不同的中間件都有什么優點和缺點&#xff1f;3.分庫分表的方式(水平分庫,垂直分庫,水平分表,垂直分表)3.1 水平分庫3.2 垂直分庫3.3 水平分表3.4 垂直分表 4.分庫分表帶來的問題4.1 事務一致性問題4.2 跨節點關聯…

【退役之重學 SQL】什么是笛卡爾積

一、初識笛卡爾積 概念&#xff1a; 笛卡爾積是指在關系型數據庫中&#xff0c;兩個表進行 join 操作時&#xff0c;沒有指定任何條件&#xff0c;導致生成的結果集&#xff0c;是兩個表中所有行的組合。 簡單來說&#xff1a; 笛卡爾積是兩個表的乘積&#xff0c;結果集中的每…

力扣 454題 四數相加Ⅱ 記錄

題目描述 給你四個整數數組 nums1、nums2、nums3 和 nums4 &#xff0c;數組長度都是 n &#xff0c;請你計算有多少個元組 (i, j, k, l) 能滿足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0示例 1&#xff1a; 輸入&#xff1a;nums1 …

Flutter 中的 SliverOpacity 小部件:全面指南

Flutter 中的 SliverOpacity 小部件&#xff1a;全面指南 Flutter 是一個功能強大的 UI 框架&#xff0c;由 Google 開發&#xff0c;允許開發者使用 Dart 語言來構建高性能、美觀的跨平臺應用。在 Flutter 的滾動組件體系中&#xff0c;SliverOpacity 是一個用來為其子 Slive…

強化學習中Q值的概念

在強化學習中&#xff0c;Q值是一個非常核心的概念&#xff0c;用來表示在給定的狀態下&#xff0c;采取某個特定動作所期望獲得的總回報。Q值基本上是一種衡量“動作價值”的方式&#xff0c;即在當前狀態采取一個動作能帶來多大價值。 定義和計算 Q值通常表示為 (Q(s, a))&…

RabbitMQ小結

MQ分類 Acitvemq kafka 優點&#xff1a;性能好&#xff0c;吞吐量高百萬級&#xff0c;分布式&#xff0c;消息有序 缺點&#xff1a;單機超過64分區&#xff0c;cpu會飆高&#xff0c;消費失敗不支持重試 &#xff0c; Rocket 阿里的mq產品 優點&#xff1a;單機吞吐量也…

香橙派 Kunpeng Pro:基于ncnn的深度學習模型量化與部署實踐

一 引言 近10年里以深度學習為代表的機器學習技術在圖像處理&#xff0c;語音識別&#xff0c;自然語言處理等領域里取得了非常多的突破&#xff0c;其背后的核心算法是深度學習為代表的AI基礎模型。 一般來講&#xff0c;我們進行AI項目研發時&#xff0c;遵循三個步驟。 第…

LabVIEW步進電機的串口控制方法與實現

本文介紹了在LabVIEW環境中通過串口控制步進電機的方法&#xff0c;涵蓋了基本的串口通信原理、硬件連接步驟、LabVIEW編程實現以及注意事項。通過這些方法&#xff0c;用戶可以實現對步進電機的精確控制&#xff0c;適用于各種自動化和運動控制應用場景。 步進電機與串口通信…

python3.8環境下安裝pyqt5

1.實驗目的 測試python可視化工具包pyqt5,為后期做系統前端頁面做鋪墊 2.實驗環境 1.軟件 anaconda2.5 pycharm2024.1.1 pyqt5 2.硬件 GPU 4070TI Intel I7 1400K 3. 安裝步驟 (base) C:\Users\PC>conda -V conda 23.7.4(base) C:\Users\PC>conda create qttest p…

spring項目修改時間格式

一、配置方式 在application.yml上添加 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 二、注解方式 1、添加依賴 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId&…

解釋def __int__(self):和def __init__(self):的區別

文章目錄 __init__ 方法例子 __int__ 方法例子 總結 def __int__(self): 和 def __init__(self): 是Python中兩個不同的特殊方法&#xff08;或魔法方法&#xff09;&#xff0c;它們有著不同的用途和含義。 __init__ 方法 作用&#xff1a;__init__ 方法是類的構造函數。當你…

大文件分片【筆記】

createChunk.js Spark-md5計算文件各分片MD5生成文件指紋 可以幫助我們更加方便地進行文件哈希計算和文件完整性檢測等操作。 import sparkMd5 from ./sparkmd5.jsexport function createChunk(file, index, chunkSize) {return new Promise((resolve, reject) > {const sta…

整理好了!2024年最常見 20 道 Kafka面試題(一)

一、什么是Apache Kafka&#xff0c;它主要用于什么場景&#xff1f; Apache Kafka是一個分布式流處理平臺&#xff0c;最初由LinkedIn開發&#xff0c;后來成為Apache軟件基金會的一個開源項目。它被設計為一個高吞吐量、可擴展、容錯的消息隊列系統&#xff0c;能夠處理實時…

【java】【python】leetcode刷題記錄--棧與隊列

232 用棧實現隊列 題目描述 兩個棧模擬隊列的思路是利用棧&#xff08;后進先出結構&#xff09;的特性來實現隊列&#xff08;先進先出結構&#xff09;的行為。這種方法依賴于兩個棧來逆轉元素的入隊和出隊順序&#xff0c;從而實現隊列的功能。 入隊操作&#xff08;使用s…