python中有些資料結構是可以透過for來loop裡面所有的item的,像是list, tuple, dict, str還有file都可以。在使用上其實for迴圈會呼叫物件中的iter(),此函式會回傳一個Iterator(迭代器),Iterator會透過next 函式來一次一次的取得下一個item,並在沒有下一個item的時候拋出StopIteration來告訴for迴圈迭代結束。
像這種有按照Iteration Protocol定義iter 和next 的物件又被稱為Iterable
1 2 3 4 5 >>> for item in [1 , 2 , 3 , 4 ]>>> for item in (1 , 2 , 3 , 4 )>>> for item in {'one' : 1 , 'two' : 2 }>>> for item in 'python' >>> for line in open ('file' )
如果希望自己定義的物件是Iterable,只要透過在class內實作iter 和next (讓python的build-in函式iter()和next()可以呼叫)就可以達成。
假設我們建立了一個物件可以設定一個字串,並在每次iteration的時候透過ascii回傳每個字元的下一個字元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Transform : def init (self, data ): self.data = data self.i = 0 self.n = len (data) def iter (self ): return self def next (self ): if self.i == self.n: raise StopIteration item = chr (ord (self.data[self.i]) + 1 ) self.i = self.i + 1 return item
宣告一個Transform物件,並用for來讀取每一個值
1 2 3 4 5 6 7 8 9 >>> t = Transform('python' )>>> for item in t: >>> print (item)q z u i p o
宣告一個Transform物件,並呼叫iter並用next來讀取每一個值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 >>> t = Transform('python' )>>> t2 = iter (t)>>> next (t2)q >>> next (t2)z >>> next (t2)u >>> next (t2)i >>> next (t2)p >>> next (t2)o >>> next (t2) Traceback (most recent call last): File <stdin>, line 1 , in next (t2) StopIteration
除了透過定義iter 和next 讓自己的物件為iterable,也可以透過在class中定義getitem 來達成。兩者只要有定義其中一種,都可以讓for loop來依序讀取物件中的item
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Transform : def init (self, data ): self.data = data self.i = 0 self.n = len (data) def getitem (self, i ): return chr (ord (self.data[i]) + 1 ) >>> t = Transform('python' )>>> for item in t: >>> print (item)q z u i p o
參考資料:Python docs - Iterators Python docs - Iterator types Python docs - Iterable