迭代與迭代器
阿新 • • 發佈:2018-11-25
迭代
使用for迴圈遍歷取值的過程叫做迭代,比如:使用for迴圈遍歷列表獲取值的過程
for value in [2, 3, 4]:
print(value)
使用for迴圈遍歷取值的物件叫做可迭代物件, 比如:列表、元組、字典、集合、range、字串
如何判斷物件是否是可迭代物件
from collections import Iterable # 判斷物件是否是指定型別 result = isinstance((3, 5), Iterable) print("元組是否是可迭代物件:", result) 結果 :True result = isinstance([3, 5], Iterable) print("列表是否是可迭代物件:", result) 結果 :True result = isinstance(5, Iterable) print("整數是否是可迭代物件:", result) 結果 :False
如何自定義一個可迭代物件
在類裡面定義__iter__方法建立的物件就是可迭代物件
from collections import Iterable # 自定義可迭代物件: 在類裡面定義__iter__方法建立的物件就是可迭代物件 class MyList(object): def __init__(self): self.my_list = list() # 新增指定元素 def append_item(self, item): self.my_list.append(item) def __iter__(self): # 可迭代物件的本質:遍歷可迭代物件的時候其實獲取的是可迭代物件的迭代器, 然後通過迭代器獲取物件中的資料 pass my_list = MyList() my_list.append_item(1) my_list.append_item(2) result = isinstance(my_list, Iterable) print(result) for value in my_list: print(value) 執行結果: Traceback (most recent call last): True File "/Users/hbin/Desktop/untitled/aa.py", line 24, in <module> for value in my_list: TypeError: iter() returned non-iterator of type 'NoneType' ##通過執行結果可以看出來,遍歷可迭代物件依次獲取資料需要迭代器
迭代器
如下程式碼會介紹到如何自定義迭代器,如何判斷是否是可迭代物件
在類裡面定義__iter__和__next__方法建立的物件就是迭代器物件
iter()函式與next()函式
iter函式: 獲取可迭代物件的迭代器,會呼叫可迭代物件身上的__iter__方法
next函式: 獲取迭代器中下一個值,會呼叫迭代器物件身上的__next__方法
from collections import Iterable, Iterator # 自定義可迭代物件 class MyList(object): def __init__(self): # 初始化一個列表 self.one_list = list() def append(self, num): self.one_list.append(num) # iter函式會調可迭代物件的iter方法 def __iter__(self): my_iterator = MyIterator(self.one_list) print(my_iterator) # 返回迭代器物件 return my_iterator # 自定義迭代器 class MyIterator(object): def __init__(self, one_list): self.list = one_list # 初始化下標 self.index = 0 result = isinstance(self, Iterator) print("MyIterator建立的物件是否是迭代器:",result) def __iter__(self): return self def __next__(self): if self.index < len(self.list): self.index += 1 return self.list[self.index - 1] else: # 停止迭代 raise StopIteration if __name__ == '__main__': my_list = MyList() my_list.append(1) my_list.append(2) myDeIterator = iter(my_list) # 檢查是否為可迭代物件 print(isinstance(my_list, Iterable)) #for item in myDeIterator: # print(item) while True: try: # 呼叫迭代器的__next__方法 print(next(myDeIterator)) except: break
for的本質
遍歷的是可迭代物件
for item in myDeIterator 迴圈的本質就是先通過iter()函式獲取可迭代物件my_list的迭代器,然後對獲取到的迭代器不斷呼叫next()方法來獲取下一個值並將其賦值給item,當遇到StopIteration的異常後迴圈結束。
遍歷的是迭代器
for item in myDeIterator 迴圈的迭代器,不斷呼叫next()方法來獲取下一個值並將其賦值給item,當遇到StopIteration的異常後迴圈結束。
#for item in myDeIterator:
# print(item)
#for的本質就是while 迴圈不斷呼叫inter()函式和next()函式
while True:
try:
# 呼叫迭代器的__next__方法
print(next(myDeIterator))
except:
break
生成器
生成器是一類特殊的迭代器,它不需要再像上面的類一樣寫__iter__()和__next__()方法了, 使用更加方便,它依然可以使用next函式和for迴圈取值
第一種生成器
類似於列表推導式,只是將列表推導式的[ ]改為()
# 列表推導式
my_list = [i * 2 for i in range(5)]
print(my_list)
# 建立生成器
my_generator = (i * 2 for i in range(5))
print(my_generator)
# next獲取生成器下一個值
# value = next(my_generator)
# print(value)
for value in my_generator:
print(value)
# 執行結果
[0, 2, 4, 6, 8]
<generator object <genexpr> at 0x101367048>
0
2
4
6
8
第二種生成器
在def函式裡面看到有yield關鍵字那麼就是生成器
def fibonacci(num):
a = 0
b = 1
# 記錄生成fibonacci數字的下標
current_index = 0
print("--11---")
while current_index < num:
result = a
a, b = b, a + b
current_index += 1
print("--22---")
# 程式碼執行到yield會暫停,然後把結果返回出去,下次啟動生成器會在暫停的位置繼續往下執行
yield result
print("--33---")
fib = fibonacci(5)
value = next(fib)
print(value)
value = next(fib)
print(value)
value = next(fib)
print(value)
# for value in fib:
# print(value)
# 執行結果
--11---
--22---
0
--33---
--22---
1
--33---
--22---
1