前言:
之前在迭代器、可迭代對象這一部分一直有些混淆,結合一些資料,表達我對這些概念的理解,未必都對,但是適合剛開始入手的朋友們從零開始理解
開門見山首先介紹可迭代對象和迭代器的通俗理解
迭代器就是能被next()調用得到下一次迭代值的對象,迭代器不直接保存迭代的序列值,而保存得到下一次迭代值的算法
可迭代對象就是能被iter()方法調用得到迭代器的對象,能進行for循環的必須是可迭代對象
for循環的底層實現原理:
以下是一個for循環的格式
for i in 可迭代對象: 循環體
實質是調用內建方法iter()得到迭代器對象,然后通過每次調用next(迭代器)得到i的迭代值
例如以下的代碼:
for i in x: print(i)
完全可以改寫為:
iterator = iter(x) while True: i = next(iterator) print(i)
從嚴格或者底層原理來說
迭代器或迭代器對象:實現了__next__()魔法方法的(類所實例化的)對象,該方法返回迭代器下一個值(保存得到下一個迭代值的算法)
可迭代對象:實現了__iter__()魔法方法的(類所實例化的)對象,該方法返回一個迭代器對象
實際上,next和iter是對__next__和__iter__的進一步封裝或者說next和iter在執行的時候又分別調用了內部的__next__和__iter__從而實現迭代器和可迭代對象的特性和功能
綜上,我們可以理解for循環、可迭代對象、迭代器三者的聯系:
for循環只能對可迭代對象進行,可迭代對象又需要迭代器的實現
由此,我們可以自定義實現迭代器和可迭代迭代對象,從而實現自定義的for循環效果
示例:
通過迭代器和可迭代對象實現菲波那切數列
分別定義迭代器和可迭代對象所屬的類:
class Fib:
'''定義可迭代對象所屬類''' def __init__(self,num): #num表示該數列的長度 self.a = 1 self.b = 2
self.current=self.a
self.num = num def __iter__(self): return FebIterator(self) class FibIterator(self):
'''定義迭代器類''' def __init__(self,source): self.source = source def __next__(self):
if(self.num-1>=0):
self.num = self.num-1 self.current = self.a self.a = self.b self.b = self.b+self.current #以上兩步賦值操作可省略中間變量直接寫為self.a,self.b = self.b,self.a+self,b
return self.curent
else: raise StopIteration
通過調用這兩個類的實例化對象,可以實現循環打印斐波那契數列
fib = Fib()
for i in fib: print(i)
實際上,為了簡化和方便,完全可以在一個類中同時實現__iter__()和__next__()方法,也即該類實例化的對象既是一個可迭代對象也是迭代器,代碼如下:
class Fib: def __init__(): self.a = 1 self.b = 2
sele.current = self.a def __iter__(self): return self def __next__():
if(self.num-1>=0):
self.num = self.num-1 self.current = self.a self.a = self.b self.b = self.b+self.current #以上兩步賦值操作可省略中間變量直接寫為self.a,self.b = self.b,self.a+self,b
return self.curent
else: raise StopIteration
其使用方法和之前沒有區別,反而更加簡便,前提是對迭代器和可迭代對象有清晰的理解和認識,否則會對二者概念產生混淆