首先區分可迭代物件(Iterable)
、迭代器(Iterator)
- 可迭代物件:包含
__iter__
方法的物件為可迭代物件,如List、Tuple、Dictionary - 迭代器:包含
__iter__
、__next__
方法
可迭代物件
屬於半成品 --> 而迭代器
屬於直接食用產品,生成器
屬於特殊的迭代器,生成器函式
執行後會返回生成器
以上型別判斷方法
from collections import Iterator,Iterable
from inspect import isgenerator , isgeneratorfunction
print(isgenerator(g),isinstance(g ,Iterator))
print(isgenerator(it1) , isgenerator(iter(it1)),isinstance(it1,Iterator))
以下均在for 迴圈遍歷中即是根據 iter 方法判斷該物件是否是可迭代序列
1. 定義一個可迭代類:
class Iterat():
def __init__(self):
self.arr = [1,2,3]
self.loc = 0
def __iter__(self):
for i in self.arr:
yield i
for i in Iterat():
print(i)
# 進行for迴圈遍歷時,先執行iter方法迭代化,返回一個迭代器物件,迭代器物件含有next方法,接下來通過next遍歷
上述定義中,可能出現的報錯Error
- 類class定義不含
__iter__
方法(不能識別為可迭代序列) - 類class中iter方法既沒有使用
yield
也沒有通過 `return self (簡單說就是iter方法執行後沒有返回迭代器物件)
2. 定義一個標準的迭代器:
2.1 類class生成法:
class Iterat():
def __init__(self):
self.arr = [1,2,3]
self.loc = 0
def __iter__(self):
return self # 返回自身,這裡再新建也可,殊途同歸
def next(self):
# python 2.7 中寫法: next
if self.loc < len(self.arr):
ret = self.arr[self.loc]
self.loc += 1
return ret
else:
raise StopIteration
def __next__(self):
# python 3 以上寫法
if self.loc < len(self.arr):
self.loc += 1
return self.arr[self.loc]
else:
raise StopIteration
2.2 yield 生成器法:原理:如果函式中存在yield,該函式將被作為生成器,執行後自動生成一個迭代器,且無需管理StopIteration邊界問題
for i in Iterat():
執行找iter方法,執行返回了迭代器(編譯器自動構造,self不是原有的類),此時class中的next方法不會被執行
class Iterat():
def __init__(self):
self.arr = [1,2,3]
def __iter__(self):
for i in self.arr:
yield i
生成器(Generator)是一種特殊的迭代器,是一種優化使用方式的直接使用產品(無需管理邊界問題,負責吃就完事了)
生成器生成函式(GeneratorFunction)不是生成器,是一種工廠函式
gt = ( i for i in range(3)) # 生成器構造語法糖
# 下面例子是一個生成器建構函式,凡是函式有yield,會被作為生成器建構函式處理
def genGT(list):
for item in list :
yield item
最後做一個小實驗比較下迭代器(流式讀取)與普通讀取的差異:(犧牲時間換空間,可以使用shell命令觀察記憶體、cpu變化)
it = ( i for i in range(100000000))
count = 0
s = time.time()
for i in it :
count += i
print(time.time()-s) # 31.8320000172 s
list = [ i for i in range(100000000)]
count = 0
s = time.time()
for i in list :
count += i
print(time.time()-s) # 27.4390001297 s