最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python迭代器、生成器、協(xié)程使用方式

 更新時間:2024年02月20日 08:56:19   作者:不必介懷  
這篇文章主要介紹了Python迭代器、生成器、協(xié)程使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

什么是迭代

迭代是訪問集合元素的一種方式。(迭代和遍歷非常相似)

什么是迭代器(Iterator)

迭代器是一種對象,可以記住遍歷的位置的對象。迭代器對象從集的第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。

在迭代一個可迭代對象的時候,實際上就是先獲取該對象提供的一個迭代器,然后通過這個迭代器來依次獲取對象中的每一個數(shù)據(jù)。

可迭代對象

某種數(shù)據(jù)可以通過for....in....的循環(huán)語法從其中依次拿到數(shù)據(jù)進行使用的數(shù)據(jù)類型,這種數(shù)據(jù)類型被稱為可迭代對象

檢測某個對象是否是可迭代對象的方法isinstance(待檢測對象,Iterable)

該方法檢測待檢測對象是不是Iterable迭代類的子類

如果是返回True,如果不是返回False

from collections.abc import Iterable
 
"""
isinstance(待檢測對象,Iterable(迭代類,固定寫法))
判斷待檢測對象是不是迭代類的一個子類
返回值:True可以迭代
    False不可以迭代
"""
string="fhsudfoh"
result=isinstance([1,2,3],Iterable)
print(result)

for循環(huán)的本質(zhì)

for循環(huán)的本質(zhì)是在對一個迭代器進行操作。

首先,for循環(huán)在遍歷可迭代對象的時候會把可迭代對象通過函數(shù)iter()或__iter__方法返回一個迭代器,然后在對這個迭代器對象進行操作。

迭代器可以用next()或__next__方法得到返回值,當把所有的值取完時會拋出StopIteration錯誤,這個錯誤在for循環(huán)中python會自己處理,不會展示給開發(fā)者。

自定義一個列表

class MyList(object):
# 重寫初始化方法,初始化一個數(shù)組用來存儲數(shù)據(jù)
    def __init__(self):
        self.list = []
 
    def __iter__(self):
# iter方法返回一個myIterator迭代器對象
        self.myiterator = MyIterator(self.list)
        return self.myiterator
 
    def additer(self, values):
# additer方法用于添加數(shù)據(jù)
        self.list.append(values)
 
 
class MyIterator(object):
# 初始化一個下標和接收一個外部的數(shù)組變量
    def __init__(self, my_list):
        self.list = my_list
        self.index = 0
 
    def __iter__(self):
        pass
# 當對象被迭代器返回后會自動尋找next方法,進行迭代
    def __next__(self):
        if self.index < len(self.list):
            data = self.list[self.index]
            self.index += 1
            return data
        else:
            raise StopIteration
 
 
if __name__ == "__main__":
    mylist = MyList()
    mylist.additer("張三")
    mylist.additer("李四")
    mylist.additer("王五")
    for value in mylist:
        print(value)

實現(xiàn)一個斐波那契數(shù)列

class feibonaqi(object):
    def __init__(self, num):
        self.fei_list = []
        self.num = num
        self.a = 1
        self.b = 1
        self.fei_index = 0
 
    def __iter__(self):
        return self
 
    def __next__(self):
        if self.fei_index < self.num:
            data = self.a
            self.a, self.b = self.b, self.a + self.b
            self.fei_index += 1
            return data
        else:
            raise StopIteration
 
 
if __name__ == '__main__':
    fei = feibonaqi(5)
    for i in fei:
        print(i)

什么是生成器(generator)

生成器是一個特殊的迭代器,使用了 yield 的函數(shù)被稱為生成器(generator)。

yield 是一個關(guān)鍵字,用于定義生成器函數(shù),生成器函數(shù)是一種特殊的函數(shù),可以在迭代過程中逐步產(chǎn)生值,而不是一次性返回所有結(jié)果。當在生成器函數(shù)中使用 yield 語句時,函數(shù)的執(zhí)行將會暫停,并將 yield 后面的表達式作為當前迭代的值返回。然后,每次調(diào)用生成器的 next() 方法或使用 for 循環(huán)進行迭代時,函數(shù)會從上次暫停的地方繼續(xù)執(zhí)行,直到再次遇到 yield 語句??梢灾鸩疆a(chǎn)生值,而不需要一次性計算并返回所有結(jié)果。

調(diào)用一個生成器函數(shù),返回的是一個迭代器對象。

生成器對象可以使用send()方法進行傳參。

生成器中也可以使用return,當語句執(zhí)行到return語句之后,生成器會終止迭代,拋出停止迭代的異常。

創(chuàng)建生成器的兩種方式

使用推導式創(chuàng)建

result_list = (x * 2 for x in range(10))
print(result_list)
# 使用生成器生成一個偶數(shù)數(shù)列[0,2,4,6,8,10,12,14,16,18]
# 這邊使用next先取出第一個值,后面for循環(huán)遍歷出來的結(jié)果是從0后面開始的
value = next(result_list)
print(value)
 
for i in result_list:
    print(i, end=" ")

使用函數(shù)創(chuàng)建

def mygenerator():
    num_list = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    num_index = 0
    while True:
        if num_index < len(num_list):
            yield num_list[num_index]
        num_index += 1
 
 
if __name__ == '__main__':
    mg = mygenerator()
    value = next(mg)
    print(value)
 
    value = next(mg)
    print(value)
 
    value = next(mg)
    print(value)

使用generator實現(xiàn)斐波那契數(shù)列

def feibonaqi(num):
    a = 1
    b = 1
    count_index = 0
    while count_index < num:
        data = a
        a, b = b, a + b
        count_index += 1
        yield data
 
 
if __name__ == '__main__':
    fei = feibonaqi(5)
    # data=next(fei)
    # print(data)
    # data=next(fei)
    # print(data)
    # data=next(fei)
    # print(data)
    # data=next(fei)
    # print(data)
    # data=next(fei)
    # print(data)
    for value in fei:
        print(value)

什么是協(xié)程

協(xié)程(coroutine)又稱為微線程,是一種用戶態(tài)的輕量級線程。

使用yield可以實現(xiàn)協(xié)程,yield可以終止任務執(zhí)行,并記錄任務執(zhí)行的進度。

協(xié)程可以實現(xiàn)一個線程執(zhí)行多個任務

協(xié)程的基本實現(xiàn)

import time
 
 
def work1():
    while True:
        print("正在執(zhí)行work1。。。。。。。。")
        yield
        time.sleep(0.5)
 
 
def work2():
    while True:
        print("正在執(zhí)行work2.....。。。。。。。。")
        yield
 
 
if __name__ == '__main__':
    w1 = work1()
    w2 = work2()
    while True:
        next(w1)
        next(w2)

使用greenlet實現(xiàn)協(xié)程

"""greenlet是一個第三方庫可以提供自行調(diào)度的微線程,只需要告訴switch如何運行即可
    1、導入模塊
    2、創(chuàng)建greenlet對象
    3、使用switch實現(xiàn)線程的調(diào)度
"""
 
import time
from greenlet import  greenlet
 
def work1():
    while True:
        print("正在執(zhí)行work1。。。。。。。。")
        time.sleep(0.5)
        g2.switch()
 
 
def work2():
    while True:
        print("正在執(zhí)行work2...............")
        time.sleep(0.5)
        g1.switch()
 
 
if __name__ == '__main__':
    g1 = greenlet(work1)
    g2 = greenlet(work2)
    g1.switch()

使用gevent實現(xiàn)協(xié)程

import time
import gevent
from gevent import monkey
 
monkey.patch_all()
"""gevent也是一個第三方庫,自動調(diào)度協(xié)程,自動識別程序中的耗時操作
    使用步驟:
    1、導入模塊
    2、指派任務
    g1=gevent.spawn(work1)
    g2=gevent.spawn(work2)
    3、join()讓主線程等待協(xié)程進行結(jié)束后在退出
    注意:gevent默認不識別time.slepp(),識別的是gevent.sleep()
    可以使用打補丁的方式解決,猴子模塊
    from gevent import monkey
    破解所有monkey.patch_all()
"""
 
 
def work1():
    while True:
        print("正在執(zhí)行work1。。。。。。。。")
        time.sleep(0.5)
        # gevent.sleep(0.5)
 
 
def work2():
    while True:
        print("正在執(zhí)行work2...........")
        time.sleep(0.5)
        # gevent.sleep(0.5)
 
 
if __name__ == '__main__':
    g1 = gevent.spawn(work1)
    g2 = gevent.spawn(work2)
    g1.join()
    g2.join()

進程、線程、協(xié)程的區(qū)別

進程是資源分配的基本單位、線程是CPU調(diào)度的基本單位、協(xié)程是單線程中執(zhí)行多任務的方式

  • 切換效率:協(xié)程>線程>進程
  • 高效率方式:進程+協(xié)程

選擇問題

  • 多進程:密集CPU任務,需要充分使用多核CPU資源(服務器,大量的并行計算)的時候,用多進程
  • 缺陷:多個進程間通信成本高,切換開銷大
  • 多線程:密集I/O任務(網(wǎng)絡(luò)I/O、磁盤I/O、數(shù)據(jù)庫I/O)使用多線程合適
  • 缺陷:同一個時間切片只能運行一個線程,不能做到高并行,但是可以做到高并發(fā)
  • 協(xié)程:當程序中存在大量不需要CPU的操作時(I/O),適用協(xié)程
  • 缺陷:單線程執(zhí)行,處理密集CPU和本地磁盤IO的時候,性能較低。處理網(wǎng)絡(luò)I/O性能還是比較高的

使用協(xié)程下載網(wǎng)絡(luò)的圖片

"""
使用協(xié)程的方式將網(wǎng)路上的圖片下載到本地
核心方法:urllib.request.urlopen()打開網(wǎng)址并返回對應的內(nèi)容(二進制流)
"""
import urllib.request
import gevent
from gevent import monkey
 
monkey.patch_all()
 
 
def down_image(url_image, file_name):
    # 異常處理
    try:
        # 打開網(wǎng)絡(luò)文件
        request_data = urllib.request.urlopen(url_image)
        # 打開本地文件
        with open(file_name, "wb") as file:
            # 循環(huán)讀取寫入文件
            while True:
                # 從網(wǎng)絡(luò)中讀取1024個字節(jié)的數(shù)據(jù)
                file_data = request_data.read(1024)
                # 判斷數(shù)據(jù)是否為空,不為空就寫入,為空就跳出循環(huán)
                if file_data:
                    file.write(file_data)
                else:
                    break
    except Exception:
        print("文件%s下載失敗" % file_name)
    else:
        print("文件%s下載完成" % file_name)
 
 
def main():
    img_url1 = "https://img1.baidu.com/it/u=1849885514,1853800516&fm=253&fmt=auto&app=138&f=JPG?w=500&h=500"
    img_url2 = "https://img2.baidu.com/it/u=4137380440,3737943568&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800"
    img_url3 = ("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F4e3acf5c-a0fc-44a2"
                "-99ff-94f69cae80b4%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com"
                "&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1709038944&t=f8e32fd271bb9215553250f0deb5e23d")
    # joinall()將傳入的線程,等待運行完成在結(jié)束進程
    gevent.joinall([
        gevent.spawn(down_image, img_url1, "img1"),
        gevent.spawn(down_image, img_url2, "img2"),
        gevent.spawn(down_image, img_url3, "img3")
    ])
 
 
if __name__ == '__main__':
    main()

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 在Django中使用MQTT的方法

    在Django中使用MQTT的方法

    這篇文章主要介紹了在Django中使用MQTT的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • Python批量重命名同一文件夾下文件的方法

    Python批量重命名同一文件夾下文件的方法

    這篇文章主要介紹了Python批量重命名同一文件夾下文件的方法,涉及Python使用os模塊操作文件的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • Python Tkinter Menu控件使用詳解

    Python Tkinter Menu控件使用詳解

    Menu控件(菜單控件)可以說是 GUI 中“精髓所在”,它以可視化的方式將一系列的命令進行分組,在每一個分組下又可以“隱藏”許多的程序執(zhí)行命令(即功能)。本文將詳細介紹它的使用,需要的可以參考一下
    2022-01-01
  • Python基礎(chǔ)之類的定義和使用詳解

    Python基礎(chǔ)之類的定義和使用詳解

    在Python中,類表示具有相同屬性和方法的對象的集合。在使用類時,需要先定義類,然后再創(chuàng)建類的實例,通過類的實例就可以訪問類中的屬性和方法了。本文就來和大家一起聊聊Python中類的定義和使用,需要的可以參考一下
    2022-08-08
  • 使用Python操作Redis的完整指南

    使用Python操作Redis的完整指南

    Redis作為業(yè)界主流的內(nèi)存數(shù)據(jù)庫,配合Python的redis-py庫,能在不改變業(yè)務代碼結(jié)構(gòu)的前提下,把數(shù)據(jù)庫的查詢壓力降低90%以上,今天我們就從零開始,聊聊怎么用Python操作Redis,搭一套真正能打的緩存系統(tǒng),需要的朋友可以參考下
    2026-03-03
  • python中open函數(shù)的基本用法示例

    python中open函數(shù)的基本用法示例

    這篇文章主要給大家介紹了關(guān)于python中open函數(shù)的基本用法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • Python OpenCV 基于圖像邊緣提取的輪廓發(fā)現(xiàn)函數(shù)

    Python OpenCV 基于圖像邊緣提取的輪廓發(fā)現(xiàn)函數(shù)

    這篇文章主要介紹了Python OpenCV 基于圖像邊緣提取的輪廓發(fā)現(xiàn)函數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • C語言中printf()函數(shù)的全面介紹及用法(簡單易懂)

    C語言中printf()函數(shù)的全面介紹及用法(簡單易懂)

    在C語言中,printf()是常用的輸出函數(shù),包含在頭文件中,它使用格式控制字符串,其中包括格式字符、轉(zhuǎn)義字符和普通字符,格式字符以"%"開頭,文中將用法介紹的非常詳細,需要的朋友可以參考下
    2024-09-09
  • Python中字典和列表的索引效率分析及實戰(zhàn)結(jié)果

    Python中字典和列表的索引效率分析及實戰(zhàn)結(jié)果

    Python中的索引是一種訪問數(shù)據(jù)結(jié)構(gòu)中特定元素的方法,它在各種數(shù)據(jù)類型中都有應用,包括字符串、列表、元組和字典,這篇文章主要介紹了Python中字典和列表的索引效率分析及實戰(zhàn)結(jié)果的相關(guān)資料,需要的朋友可以參考下
    2026-03-03
  • python中from module import * 的一個坑

    python中from module import * 的一個坑

    from module import *把module中的成員全部導到了當前的global namespace,訪問起來就比較方便了。當然,python style一般不建議這么做,因為可能引起name conflict。
    2014-07-07

最新評論

乐安县| 上犹县| 左云县| 喜德县| 麻城市| 峨山| 醴陵市| 卫辉市| 济阳县| 谢通门县| 教育| 邻水| 闻喜县| 泾阳县| 寿光市| 太仓市| 惠东县| 五台县| 天气| 洛浦县| 桐城市| 临泉县| 云阳县| 临颍县| 霍林郭勒市| 兴化市| 曲沃县| 万山特区| 曲靖市| 南安市| 延长县| 新和县| 沂水县| 旬邑县| 大石桥市| 柏乡县| 喜德县| 同心县| 遂平县| 滦平县| 方山县|