日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python基础教程:自定义迭代器

發布時間:2025/3/20 python 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python基础教程:自定义迭代器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文介紹如何自定義迭代器,涉及到類的運算符重載,包括__getitem__的索引迭代,以及__iter__、__next__和__contains__,如果不了解這些知識可跳過本文。

索引迭代方式

索引取值和分片取值

元組、列表、字典、集合、字符串都支持索引取值操作和分片操作。

>>> L = [11,21,31,41] >>> L[0] 11 >>> L[0:2] [11, 21]

分片操作實際上將一個slice對象當作索引位傳遞給序列,然后以索引取值的方式取得所需元素。

>>> L[0:2] [11, 21]>>> L[slice(0,2)] [11, 21]

slice對象由slice()函數創建,它有3個參數:起始索引位、結束索引位、步進值。例如:

>>> slice(0,2) slice(0, 2, None)

__getitem__

列表、元組等序列之所以可以索引取值、分片取值,是因為它們實現了__getitem__方法。

例如:

>>> hasattr(list,"__getitem__") True >>> hasattr(tuple,"__getitem__") True >>> hasattr(dict,"__getitem__") True >>> hasattr(str,"__getitem__") True

如果自定義類并實現__getitem__方法,它們會重載索引取值:

''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class cls:def __getitem__(self, index):print("getitem index", index)return index * 2>>> c = cls() >>> c[1] getitem index 1 2 >>> c[2] getitem index 2 4 >>> c[3] getitem index 3 6

上面的自定義類只支持索引取值,不支持分片取值。因為__getitem__中沒有編寫索引取值的方式,也就不支持傳遞slice對象來進行分片取值。

分片和__getitem__

如果想要__getitem__支持分片取值,需要在__getitem__中使用索引取值的方式,以便支持slice對象作為索引。

下面是一個簡單的支持分片操作的自定義類:

class cls:def __init__(self,data):self._data = datadef __getitem__(self,index):print("getitem:",index)return self._data[index]>>> c = cls([1,2,3,4]) >>> c[1] getitem: 1 2 >>> c[0:2] getitem: slice(0, 2, None) [1, 2]

__setitem__和__delitem__

如果想要索引或者分片賦值,那么會調用__setitem__()方法,如果想要刪除索引值或分片值,會調用__delitem__()方法。

''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class cls:def __init__(self,data):self._data = datadef __getitem__(self,index):print("in getitem")return self._data[index]def __setitem__(self,index,value):print("in setitem")self._data[index] = valuedef __delitem__(self,index):print("in delitem")del self._data[index]def __repr__(self):return str(self._data)>>> c = cls([11,22,33,44,55]) >>> c[1:3] in getitem [22, 33] >>> c[1:3] = [222,333] in setitem >>> c [11, 222, 333, 44, 55] >>> del c[1:3] in delitem

__getitem__索引迭代

__getitem__重載了索引取值和分片操作,實際上它也能重載索引的迭代操作。以for為例,它會循環獲取一個個的索引并向后偏移,直到超出索引邊界拋出IndexError異常而停止。

此外,__getitem__重載使得它可以被迭代,也就是它通過數值索引的方式讓這個對象變成可迭代對象,所有迭代工具(比如zip/map/for/in)都可以對這個對象進行迭代操作。

class cls:def __init__(self,data):self._data = datadef __getitem__(self,index):return self._data[index]def __repr__(self):return str(self._data)>>> c1 = cls([11,22,33,44,55]) >>> I = iter(c1) >>> next(I) 11 >>> 22 in I True>>> I=iter(c1) >>> for i in I:print(i,end=" ") ... 11 22 33 44 55

可迭代對象:__iter__和__next__

定以了__getitem__的類是可迭代的類型,是通過數值索引的方式進行迭代的,但這是退而求其次的行為,更好的方式是定義__iter__方法,使用迭代協議進行迭代。當同時定義了__iter__和__getitem__的時候,iter()函數優先選擇__iter__,只有在__iter__不存在的時候才會選擇__getitem__。

例如:

''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class Squares:def __init__(self, start, stop): # 迭代起始、終止位self.value = startself.stop = stopdef __iter__(self): # 返回自身的迭代器return selfdef __next__(self): # 返回下一個元素if self.value > self.stop: # 結尾時拋出異常raise (StopIteration)item = self.value**2self.value += 1return itemif __name__ == "__main__":for i in Squares(1, 5):print(i, end=" ")s = Squares(1,5)print()print(9 in s)

運行結果:

1 4 9 16 25 True

因為上面的類中同時定義了__iter__和__next__,且__iter__返回的是自身,所以這個類型的每個迭代對象都是單迭代的。

>>> s = Squares(1,5) >>> I1 = iter(s) # I1和I2迭代的是同一個對象 >>> I2 = iter(s) >>> next(I1) 1 >>> next(I2) # 繼續從前面的位置迭代 4 >>> next(I1) 9

自定義多迭代類型

要定義多迭代的類型,要求__iter__返回一個新的迭代對象,而不是self自身,也就是說不要返回自身的迭代器。

例如:

# 返回多個獨立的可迭代對象 class MultiIterator:def __init__(self, wrapped):self.wrapped = wrapped # 封裝將被迭代的對象def __iter__(self):return Next(self.wrapped) # 返回獨立的可迭代對象# 自身的迭代器 class Next:def __init__(self, wrapped):self.wrapped = wrappedself.offset = 0def __iter__(self):return selfdef __next__(self): # 返回下一個元素if self.offset >= len(self.wrapped):raise (StopIteration)else:item = self.wrapped[self.offset]self.offset += 1return item # 返回指定索引位置處的元素if __name__ == "__main__":string = "abc"s = MultiIterator(string)for x in s:for y in s:print(x + y, end=" ")

每個for迭代工具都會先調用iter()來獲取可迭代對象,然后調用next()獲取下一個元素。而這里的iter()會調用MultiIterator的__iter__來獲取可迭代對象,而MultiIterator所返回的可迭代對象是相互獨立的Next對象,因此for x in x和for y in s所迭代的是不同迭代對象,它們都有記錄著自己的迭代位置信息。

總結

以上是生活随笔為你收集整理的Python基础教程:自定义迭代器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。