Python 函式進階-迭代器

小小垂髫發表於2022-04-21

迭代器

什麼是迭代器

能被 next 指標呼叫,並不斷返回下一個值的物件,叫做迭代器。表示為Iterator,迭代器是一個物件型別資料。

概念

迭代器指的是迭代取值的工具,迭代是一個重複的過程,每次重複都是基於上一次的結果而繼續的,單純的重複並不是迭代。

特徵

迭代器並不依賴索引,而通過 next 指標迭代所有資料,一次只取一個值,大大節省空間。

惰性序列

惰性序列是指沒有一次性的把所有資料都放在序列中,而是遍歷一個放一個這樣的序列,range物件和迭代器能夠產生惰性序列。

檢查可迭代物件

for迴圈的用於遍歷可迭代物件,簡單粗暴的來說,可以被for迴圈遍歷的元素都是可迭代物件。for 迴圈能夠遍歷一切可迭代性資料的原因在於,底層呼叫了迭代器,通過next方法中的指標實現資料的獲取。所以普通的非迭代器可迭代物件和迭代器之間的區別就是,一個不能直接使用next呼叫,一個可以被next指標呼叫。

再次重複一遍,可迭代物件不一定是迭代器,迭代器一定是一個可迭代物件

使用dir()函式可以檢視一個資料中的所有的物件成員,如果包含有__iter__方法,說明就是一個可迭代物件。換句話說,__iter__方法的作用就是返回一個可迭代物件。

# 定義一個列表,列表是可迭代物件
lst = [1, 2, 3, 4, 5]

# 獲取列表的所有成員
res_lst = dir(lst)

print(res_lst)
'''
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
'''

# 檢視是否存在__iter__方法
res = '__iter__' in res_lst

print(res)  # True

# 存在__iter__方法,說明確實是一個可迭代物件

定義迭代器

迭代器的表示方式是iterator

使用iter函式

使用 iter 函式將一個普通的可迭代物件轉成迭代器。

lst = [1, 2, 3]

print(type(lst))    # <class 'list'>

it = iter(lst)

print(type(it))     # <class 'list_iterator'>

使用__iter__方法

使用 __iter__ 內建方法實現可迭代物件轉成迭代器。

lst = [1, 2, 3]

print(type(lst))    # <class 'list'>

it = lst.__iter__()

print(type(it))     # <class 'list_iterator'>

生成器

生成器詳細說明。

判斷迭代器

檢查內建方法

存在__iter__方法說明是可迭代物件。存在 __next__ 方法說明是迭代器,因為迭代器可以使用next指標獲取元素。

迭代器中,__iter____next__都存在。

產卡是可迭代物件。

# 列表
lst = list()

# 迭代器
lst_it = iter(lst)

# 迭代器中的所有成員
res_lst = dir(lst_it)

# 判斷
if '__iter__' in res_lst:
	print('lst_it是一個可迭代物件')

if '__next__' in res_lst:
	print('lst_it是一個迭代器')

'''
結果:
lst_it是一個可迭代物件
lst_it是一個迭代器
'''

使用collections模組

匯入collections模組中的IteratorIterable型別可以判斷是否是可迭代物件或者是迭代器。Iterator是迭代器型別資料。Iterable是可迭代物件型別資料。利用匯入的資料型別配合isinstance函式就可以判斷資料的型別。

lst = list()

lst_it = iter(lst)

# 判斷是否是迭代器
res = isinstance(lst_it, Iterator)
print(res)  # True

# 判斷是否是可迭代物件
res = isinstance(lst_it, Iterable)
print(res)  # True

呼叫迭代器

呼叫迭代器的幾種方法

  1. 使用next函式或者是__next__內建方法一個一個、一遍一遍的獲取其中的資料;
  2. 使用for迴圈遍歷出來;
  3. 使用while迴圈配合next函式或者是__next__內建方法;
  4. 強轉成為其它的資料型別;

使用next方法和函式

呼叫迭代器使用next函式才可以取出其中的內容,next 在呼叫迭代器中的資料時單向不可逆的,是一條路走到黑的過程,如果呼叫超出迭代器中的元素個數,會報錯StopIteration ,意為停止迭代。

# 因為lst本沒有資料,所以無法取出資料
lst = list()

lst_it = iter(lst)

res = next(lst_it)  # StopIteration

print(res)

取出迭代器中的資料,如果資料全部取出要重置迭代器才能再次取出。

lst = [1, 2, 3]

lst_it = iter(lst)

# 迭代器中一次只會取出一個資料
print(next(lst_it))  # 1
print(next(lst_it))  # 2
print(next(lst_it))  # 3

# 超出迭代器中的元素個數,就會報錯
print(next(lst_it))  # StopIteration

# 如果要重新取出資料,就重置迭代器,重新定義一邊迭代器就是重置迭代器
lst_it = iter(lst)

# 再次取出資料,使用__next__方法
print(lst_it.__iter__())  # 1
print(lst_it.__iter__())  # 2
print(lst_it.__iter__())  # 3

總結

  1. 使用next函式呼叫
  2. 使用for迴圈遍歷
  3. 強轉成為其它的資料型別(實測容器都可以轉成迭代器,但是迭代器只有轉成列表才會有內容)
  4. next函式配合迴圈遍歷

相關文章