Python中可迭代物件、迭代器以及iter()函式的兩個用法詳解
在Python中,有這兩個概念容易讓人混淆。第一個是可迭代物件(Iterable),第二個是迭代器(Iterator),第三個是生成器(Generator),這裡暫且不談生成器。
可迭代物件
列表、元組、字串、字典等都是可迭代物件,可以使用for迴圈遍歷出所有元素的都可以稱為可迭代物件(Iterable)。在Python的內建資料結構中定義了Iterable這個類,在collections.abc模組中,我們可以用這個來檢測是否為可迭代物件
>>> from collections import Iterable
>>> a = [1,2,3]
>>> isinstance(a, Iterable)
>>> True
>>> b = 'abcd'
>>> isinstance(b, Iterable)
>>> True
這些資料結構之所以能稱之為Iterable,是因為其內部實現了__iter__()
方法,從而可迭代。當我們使用for迴圈時,直譯器會呼叫內建的iter()函式,呼叫前首先會檢查物件是否實現了__iter__()
方法,如果有就呼叫它獲取一個迭代器(接下來會講)。加入沒有__iter__()
方法,但是實現了__getitem__()
方法,直譯器會建立一個迭代器並且按順序獲取元素。如果這兩個方法都沒有找到,就會丟擲TypeError異常。下面我們自定義物件,分別實現這兩個方法(getitem(), iter())
'''
遇到問題沒人解答?小編建立了一個Python學習交流QQ群:778463939
尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
'''
class MyObj:
def __init__(self, iterable):
self._iterable = list(iterable)
def __getitem__(self, item):
return self._iterable[item]
obj = MyObj([1,2,3])
for i in obj:
print(i)
如上所示,這裡沒有實現__iter__
方法,只實現了__getitem__
方法,也使得Myobj稱為可迭代物件。
下面我們實現__iter__
方法,這裡使用了yield語法用來產出值(這裡需要生成器的知識)
class MyObj:
def __init__(self, iterable):
self._iterable = list(iterable)
def __iter__(self):
index = 0
while True:
try:
yield self._iterable[index]
except IndexError:
break
index += 1
obj = MyObj([1,2,3])
for i in obj:
print(i)
這裡同樣讓物件稱為可迭代物件。
迭代器
迭代器是一個可以記住遍歷的位置的物件。
迭代器物件從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。
如上圖所示,迭代器(Iterator)繼承可迭代(Iterable),迭代器必須實現__iter__
方法和__next__
方法。其中__next__
方法用於產出下一個元素。
由繼承圖可見,迭代器一定是可迭代物件,可迭代物件不一定是迭代器
迭代器有兩個基本的方法:iter() 和 next()。
我們使用iter(iterable)即可把可迭代物件轉換成迭代器
使用next(iterator)來獲取迭代器的下一個值
'''
遇到問題沒人解答?小編建立了一個Python學習交流QQ群:778463939
尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
'''
>>> a = [3,4,5]
>>> a
>>> [3, 4, 5]
>>> iter(a)
>>> <list_iterator object at 0x10b130ba8>
>>> iterator = iter(a)
>>> next(iterator)
>>> 3
>>> next(iterator)
>>> 4
>>> next(iterator)
>>> 5
>>> next(iterator)
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
如上所示,因為物件實現了__next__
方法,我們可以通過next(iterator)來獲取迭代器的下一個值,直到沒有值了,丟擲StopIteration異常結束。
迭代器的背後
迭代器Iterator是一個抽象基類,它定義在_collections_abc.py
中
Iterator原始碼如下
class Iterator(Iterable):
__slots__ = ()
@abstractmethod
def __next__(self):
'Return the next item from the iterator. When exhausted, raise StopIteration'
raise StopIteration
def __iter__(self):
return self
@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
return _check_methods(C, '__iter__', '__next__')
return NotImplemented
可以看到,它實現了__subclasshook__
方法,即不用顯式繼承Iterator,只需要實現__iter__
和__next__
方法即可稱為Iterator的虛擬子類。這裡凸現了Python的鴨子型別,實現特定的“協議”即可擁有某種行為。
另外,它自己也定義了__iter__
方法,當我們使用iter(Iterator)時直接返回自己,不做任何處理。
iter()函式的兩個用法
官方文件中給出了說明:
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
第一個用法:iter(iterable) -> iterator (把可迭代物件轉換為迭代器)
第二個用法:iter(callable, sentinel) -> iterator (第一個引數:任何可呼叫物件,可以是函式,第二個是標記值,當可呼叫物件返回這個值時,迭代器丟擲StopIteration異常,而不產出標記值)
'''
遇到問題沒人解答?小編建立了一個Python學習交流QQ群:778463939
尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
'''
>>> from random import choice
>>> values = [1,2,3,4,5,6,7]
>>> def test_iter():
>>> return choice(values)
>>> it = iter(test_iter, 2)
>>> it
>>> <callable_iterator object at 0x10b130b00>
>>> for i in it:
>>> print(i)
>>> 7
>>> 1
>>> 7
>>> 3
>>> 1
上面程式碼的流程:test_iter函式從values列表中隨機挑選一個值並返回,呼叫iter(callable, sentinel)函式,把sentinel標記值設定為2,返回一個callable_iterator例項,遍歷這個特殊的迭代器,如果函式返回標記值2,直接丟擲異常退出程式。這就是iter函式的鮮為人知的另一個用法。
相關文章
- 迭代器與可迭代物件的區別,以及iter()函式的使用。物件函式
- Python可迭代的物件與迭代器Python物件
- Python生成器、迭代器、可迭代物件Python物件
- Python迭代和迭代器詳解Python
- Python之可迭代物件、迭代器、生成器Python物件
- 你知道JavaScript中的可迭代物件與迭代器嗎JavaScript物件
- 關於python中可迭代物件和迭代器的一些理解Python物件
- 可迭代物件、迭代器、生成器物件
- python可迭代物件Python物件
- 搞清楚 Python 的迭代器、可迭代物件、生成器Python物件
- 可迭代物件 vs 迭代器 vs 生成器物件
- 重要內建函式、常見內建函式(瞭解)、可迭代物件、迭代器物件、for迴圈原理、異常捕獲函式物件
- Python 函式進階-迭代器Python函式
- Python函式:一個簡單的迭代Python函式
- Python——迭代器的高階用法Python
- JavaScript的迭代函式與迭代函式的實現JavaScript函式
- ES6中的迭代器、Generator函式以及Generator函式的非同步操作函式非同步
- 第一類物件(函式),閉包及迭代器物件函式
- python中的迭代器Python
- 跟你深入剖析可迭代物件和迭代器的區別與聯絡物件
- Iterator與Iterable(迭代器與可迭代)
- 生成器函式,迭代器函式
- 詳解C#迭代器C#
- 關於我對可迭代物件,迭代器,生成器的一些理解物件
- Python3中的列表生成式、生成器與迭代器例項詳解Python
- Python中迭代器的實現Python
- Python中enumerate函式用法詳解Python函式
- Python進階:迭代器與迭代器切片Python
- python_August(迭代器、生成式)Python
- Python 迭代器Python
- Python迭代器Python
- Python:迭代器Python
- 不用for迭代 --手工訪問迭代器中的元素.
- 《python-美藏篇》1.可迭代、迭代器與生成器Python
- java基礎之:迭代器詳解Java
- 理解Python的迭代器Python
- Java——深入瞭解Java中的迭代器Java
- PHP 物件迭代PHP物件