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

Python可迭代對(duì)象與迭代器的用法及說(shuō)明

 更新時(shí)間:2026年04月08日 09:17:45   作者:掐死你滴溫柔  
文章主要介紹了迭代器和可迭代對(duì)象的概念、Python中如何判斷一個(gè)對(duì)象是否可迭代、序列為什么可迭代、如何使用iter()函數(shù)處理可調(diào)用對(duì)象、Python中迭代器的接口以及Sentence類的迭代器實(shí)現(xiàn)

迭代是數(shù)據(jù)處理的基石:程序?qū)⒂?jì)算應(yīng)用于數(shù)據(jù)序列。如果數(shù)據(jù)太大,在內(nèi)存中放不下,則需要采用“惰性”的方式獲取數(shù)據(jù),即只按需獲取和處理數(shù)據(jù)項(xiàng)的一部分,而不是一次性加載整個(gè)數(shù)據(jù)集。這就是迭代器的作用。

在Python中,所有容器類型都是可迭代對(duì)象。Python使用可迭代對(duì)象提供的迭代器支持以下操作:

  • for循環(huán)
  • 列表,字典,集合推導(dǎo)式
  • 拆包賦值
  • 構(gòu)造容器實(shí)例

單詞序列

首先我們通過(guò)下面代碼開(kāi)啟可迭代對(duì)象之旅。

import re
import reprlib

RE_WORD = re.compile(r'\w+')


class Sentence:
    def __init__(self, text: str):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __len__(self):
        return len(self.words)

    def __getitem__(self, index):
        return self.words[index]

    def __repr__(self):
        # reprlib.repr這個(gè)實(shí)用函數(shù)用于生成大型模型結(jié)構(gòu)的簡(jiǎn)略字符串表現(xiàn)形式
        return f"Sentence({reprlib.repr(self.text)})"

我們測(cè)試一下上面的代碼:

s = Sentence(text="靜夜思:唐【李白】 床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉(xiāng)。")
print(s)   # 輸出:Sentence('靜夜思:唐【李白】 床前...。舉頭望明月,低頭思故鄉(xiāng)。')
for i in s:
    print(i)
print(s[0]) # 靜夜思
print(s[-1]) # 低頭思故鄉(xiāng)
print(list(s))  # 輸出:['靜夜思', '唐', '李白', '床前明月光', '疑是地上霜', '舉頭望明月', '低頭思故鄉(xiāng)']

上面代碼中傳入一個(gè)字符串,創(chuàng)建一個(gè)Sentence實(shí)例。reprlib.repr函數(shù)默認(rèn)情況下生成的字符串最多有30個(gè)字符,所以多余的字符串使用...替代。Sentence實(shí)例可以迭代,因?yàn)榭梢缘?,使用Sentence對(duì)象可用于構(gòu)建列表和其他可迭代類型。

Python開(kāi)發(fā)者都知道,序列可以迭代,為什么呢?

序列可以迭代的原因:iter函數(shù)

需要迭代對(duì)象x時(shí),Python會(huì)自動(dòng)調(diào)用iter(x)。

內(nèi)置函數(shù)iter執(zhí)行以下操作:

  • 檢查對(duì)象是否實(shí)現(xiàn)了__iter__方法,如果實(shí)現(xiàn)了就調(diào)用它,獲取一個(gè)迭代器。
  • 如果沒(méi)有實(shí)現(xiàn)__iter__方法,但是實(shí)現(xiàn)了__getitem__方法,那么iter()創(chuàng)建一個(gè)迭代器,嘗試索引(從0開(kāi)始)獲取項(xiàng)。
  • 然后嘗試失敗,則Python拋出TypeError異常,通常會(huì)提示“'C' object is not iterable”,其中C是目標(biāo)對(duì)象所屬的類。

所有Python序列可迭代的原因是,按照定義,序列都實(shí)現(xiàn)了__getitem__方法。其實(shí),標(biāo)準(zhǔn)的序列也都實(shí)現(xiàn)了__iter__方法。因此不僅實(shí)現(xiàn)了特殊方法__iter__的對(duì)象被視為可迭代對(duì)象,實(shí)現(xiàn)了__getitem__方法的對(duì)象也被視為可迭代對(duì)象。

from collections import abc
class Demo:
    def __getitem__(self, item):
        pass

class Demo1:
    def __iter__(self):
        pass

print(iter(Demo()))  # <iterator object at 0x000001E61560C610>
print(isinstance(Demo1(),abc.Iterable)) #True

值得一提的是,在Python3.10開(kāi)始,檢查對(duì)象x是否迭代,最準(zhǔn)確的方法是使用iter(x)函數(shù),如果不可迭代,則處理TypeError異常。這比isinstence(x,abc.Iterable)更準(zhǔn)確,因?yàn)閕ter(x)函數(shù)還會(huì)考慮過(guò)時(shí)的__getitem__方法,而抽象基類Iterable則不考慮。

內(nèi)置的iter()更常被Python自身使用,我們自己很少用到。iter()函數(shù)還有另一種用法,不過(guò)鮮為人知。

使用iter處理可調(diào)用對(duì)象

調(diào)用iter()時(shí),傳入兩個(gè)參數(shù)可以為函數(shù)或任何可迭代對(duì)象創(chuàng)建迭代器。對(duì)于這種用法,第一個(gè)參數(shù)必須是一個(gè)可迭代對(duì)象,重復(fù)調(diào)用產(chǎn)生值;第二個(gè)參數(shù)是哨符,即一種標(biāo)記值,如果可調(diào)用對(duì)象返回哨符,則迭代器拋出StopIteration,而不產(chǎn)出哨符。

例如下面示例:使用iter函數(shù)擲一個(gè)6面骰子,直到點(diǎn)數(shù)為1.

import random

def d6():
    return random.randint(1, 6)

d6_iter = iter(d6, 1)
print(d6_iter)
for i in d6_iter:
    print(i)
輸出:
<callable_iterator object at 0x0000016A13F82C80>
4
3
5
6
2
5
3
2
4

上面的iter函數(shù)返回的是一個(gè)callable_iterator。這個(gè)示例中的for循環(huán)可能會(huì)運(yùn)行很長(zhǎng)時(shí)間,但是絕對(duì)不會(huì)產(chǎn)生1,因?yàn)?是哨符。

可迭代對(duì)象和迭代器

由上面內(nèi)容可知,可迭代對(duì)象:使用內(nèi)置函數(shù)iter可以獲取迭代器的對(duì)象。如果對(duì)象實(shí)現(xiàn)了能返回迭代器的__iter__方法,那么對(duì)象就是可迭代的。序列都可以迭代。實(shí)現(xiàn)了__getitem__方法,而且接受從0開(kāi)始的索引,這種對(duì)象也可以迭代。

可迭代對(duì)象和迭代器之間的關(guān)系是:Python從可迭代對(duì)象中獲取迭代器。

Python中字符串是可以迭代的。表面上看不出來(lái),但是背后有一個(gè)迭代器。

s = 'ABC'
for char in s:
    print(char)

假如沒(méi)有for語(yǔ)句,我們不得不使用while循環(huán)模擬:

s='ABC'
s_iter = iter(s)
while True:
    try:
        print(next(s_iter))
    except StopIteration:
        del s_iter # 釋放s_iter的引用,即廢棄迭代器對(duì)象
        break

StopIteration表明迭代器已耗盡。內(nèi)置函數(shù)iter()在內(nèi)部自行處理for循環(huán)和其他迭代上下文(列表推導(dǎo)式,可迭代對(duì)象拆包等)的StopIteration異常。

Python標(biāo)準(zhǔn)的迭代器接口有以下兩個(gè)方法:

  • __next__:返回序列的下一項(xiàng),如果沒(méi)有項(xiàng)了,拋出StopIteration異常
  • __iter__:返回self,以便在預(yù)期可迭代對(duì)象的地方使用迭代器。例如for循環(huán)中

回到上面的Sentence類:

s = Sentence(text="靜夜思:唐【李白】 床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉(xiāng)。")
it = iter(s)
print(it)  # <iterator object at 0x0000026DBBCD3460>
print(next(it))  # 靜夜思
print(next(it))  # 唐
print(list(it))  # ['李白', '床前明月光', '疑是地上霜', '舉頭望明月', '低頭思故鄉(xiāng)']

可以清楚的看出iter()是如何構(gòu)建迭代器的,以及next()是如何使用迭代器的,以及無(wú)法重置已經(jīng)耗盡的迭代器。

為Sentence類實(shí)現(xiàn)__iter__方法

下面實(shí)現(xiàn)經(jīng)典迭代器設(shè)計(jì)模式。雖然不符合Python的習(xí)慣做法,后續(xù)會(huì)重構(gòu)。但是通過(guò)下面代碼,可以明確可迭代容器和迭代器之間的關(guān)系。

import re
import reprlib

RE_WORD = re.compile(r'\w+')


class Sentence:
    def __init__(self, text: str):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __len__(self):
        return len(self.words)

    def __repr__(self):
        # reprlib.repr這個(gè)實(shí)用函數(shù)用于生成大型模型結(jié)構(gòu)的簡(jiǎn)略字符串表現(xiàn)形式
        return f"Sentence({reprlib.repr(self.text)})"

    def __iter__(self):
        return SentenceIterator(self.words)


class SentenceIterator:
    def __init__(self, words):
        self.words = words
        self.index = 0

    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word

    def __iter__(self):
        return self

與前一版相比,這里只多了一個(gè)__iter__方法,沒(méi)有了__getitem__方法,為的是明確表明這個(gè)類之所以可以迭代,是因?yàn)閷?shí)現(xiàn)了__iter__方法。根據(jù)可迭代協(xié)議,__iter__方法實(shí)例化并返回一個(gè)迭代器(SentenceIterator)。

注意:對(duì)于上面的SentenceIterator迭代器示例來(lái)說(shuō),沒(méi)必要在類中實(shí)現(xiàn)__iter__方法,不過(guò)這樣做是對(duì)的,因?yàn)榈鲬?yīng)該實(shí)現(xiàn)__iter__和__next__這兩個(gè)方法,而且這樣做能讓迭代器通過(guò)issubclass(SentenceIterator,abc.Iterator)測(cè)試。

不要把可迭代對(duì)象變成迭代器

構(gòu)建可迭代對(duì)象和迭代器時(shí)經(jīng)常會(huì)出現(xiàn)錯(cuò)誤,原因是混淆了二者。要知道,可迭代對(duì)象有個(gè)__iter__方法,每次都實(shí)例化一個(gè)新的迭代器;而迭代器要實(shí)現(xiàn)__next__方法,返回單個(gè)元素,此外還要實(shí)現(xiàn)__iter__方法,返回本身。

因此迭代器是可迭代對(duì)象,但是可迭代對(duì)象不是迭代器。

總結(jié)

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

相關(guān)文章

  • 一篇文章帶你了解kali局域網(wǎng)攻擊

    一篇文章帶你了解kali局域網(wǎng)攻擊

    這篇文章主要給大家介紹了kali的局域網(wǎng)攻擊,小編覺(jué)得這篇文章還是不錯(cuò)的,使用起來(lái)也是非常方便的,需要的朋友可以參考下
    2021-08-08
  • Python高效計(jì)算上周五到任意日期的完全指南

    Python高效計(jì)算上周五到任意日期的完全指南

    在業(yè)務(wù)系統(tǒng)開(kāi)發(fā)中,日期計(jì)算是高頻且關(guān)鍵的需求,這篇文章將高效計(jì)算上周五到任意日期的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-08-08
  • Python2包含中文報(bào)錯(cuò)的解決方法

    Python2包含中文報(bào)錯(cuò)的解決方法

    這篇文章主要給大家介紹了關(guān)于Python2包含中文報(bào)錯(cuò)的解決方法,文中通過(guò)示例代碼詳細(xì)介紹了解決的方法,相信會(huì)對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-07-07
  • python中的繼承機(jī)制super()函數(shù)詳解

    python中的繼承機(jī)制super()函數(shù)詳解

    這篇文章主要介紹了python中的繼承機(jī)制super()函數(shù)詳解,super 是用來(lái)解決多重繼承問(wèn)題的,直接用類名調(diào)用父類方法在使用單繼承的時(shí)候沒(méi)問(wèn)題,但是如果使用多繼承,會(huì)涉及到查找順序、重復(fù)調(diào)用等問(wèn)題,需要的朋友可以參考下
    2023-08-08
  • python中的__init__ 、__new__、__call__小結(jié)

    python中的__init__ 、__new__、__call__小結(jié)

    這篇文章主要介紹了python中的__init__ 、__new__、__call__小結(jié),需要的朋友可以參考下
    2014-04-04
  • python 函數(shù)傳參之傳值還是傳引用的分析

    python 函數(shù)傳參之傳值還是傳引用的分析

    這篇文章主要介紹了python 函數(shù)傳參之傳值還是傳引用的分析,需要的朋友可以參考下
    2017-09-09
  • 一文詳解Python如何處理函數(shù)調(diào)用超時(shí)問(wèn)題

    一文詳解Python如何處理函數(shù)調(diào)用超時(shí)問(wèn)題

    在Python開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到需要控制函數(shù)執(zhí)行時(shí)間的場(chǎng)景,本文將深入探討Python中處理函數(shù)調(diào)用超時(shí)的幾種方法,感興趣的小伙伴可以參考一下
    2025-04-04
  • python實(shí)現(xiàn)21點(diǎn)小游戲

    python實(shí)現(xiàn)21點(diǎn)小游戲

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)21點(diǎn)小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 深入了解Python中Lambda函數(shù)的用法

    深入了解Python中Lambda函數(shù)的用法

    lambda函數(shù)是Python中常用的內(nèi)置函數(shù),又稱為匿名函數(shù)。和普通函數(shù)相比,它只有函數(shù)體,省略了def和return,使得結(jié)構(gòu)看起來(lái)更精簡(jiǎn)。本文將詳細(xì)說(shuō)說(shuō)Lambda函數(shù)的用法,需要的可以參考一下
    2022-09-09
  • 一文教你向Pandas?DataFrame添加行

    一文教你向Pandas?DataFrame添加行

    這篇文章主要給大家介紹了關(guān)于如何向Pandas?DataFrame添加行的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03

最新評(píng)論

连州市| 巴楚县| 大姚县| 清原| 彭泽县| 周至县| 疏附县| 台中县| 宝坻区| 运城市| 桦甸市| 五河县| 怀宁县| 葫芦岛市| 平潭县| 白山市| 贵阳市| 呼和浩特市| 寿光市| 姚安县| 博罗县| 汝南县| 达拉特旗| 孟州市| 黑山县| 沁阳市| 剑川县| 离岛区| 邛崃市| 石泉县| 涿州市| 信宜市| 江城| 登封市| 墨江| 长治县| 磴口县| 大同市| 公主岭市| 张家港市| 夏河县|