Python练习 | Python 可迭代对象 迭代器
博主github:https://github.com/MichaelBeechan
博主CSDN:https://blog.csdn.net/u011344545
在使用Python的過程中,很容易混淆如下幾個關聯的概念:
1.容器(container)
2.可迭代對象(Iterable)
3.迭代器(Iterator)
4.生成器(generator)
5.生成器表達式
6.{list, set, dict} 解析式
它們之間的關系如下表所示:
?
容器(container)
容器是用來儲存元素的一種數據結構,它支持隸屬測試,容器將所有數據保存在內存中,在Python中典型的容器有:
list, deque, …
set,frozesets,…
dict, defaultdict, OrderedDict, Counter, …
tuple, namedtuple, …
str
容器相對來說很好理解,因為你可以把它當成生活中的箱子、房子、船等等。
一般的,通過判斷一個對象是否包含某個元素來確定它是否為一個容器。例如:
字典容器通過檢查是否包含鍵來進行判斷:
字符串通過檢查是否包含某個子 串來判斷:
注意:并非所有的容器都是可迭代對象。
可迭代對象
正如前面所提到的,大部分容器都是可迭代的,但是還有其他一些對象也可以迭代,例如,文件對象以及管道對象等等,容器一般來說存儲的元素是有限的,同樣的,可迭代對象也可以用來表示一個包含有限元素的數據結構。
可迭代對象可以為任意對象,不一定非得是基本數據結構,只要這個對象可以返回一個iterator。聽起來可能有點費解,但是可迭代對象與迭代器之間有一個顯著的區別。先看下面的例子
注意:可迭代的類中,一般實現以下兩個方法,__iter__()以及__next()__方法,__iter__()方法返回self。
當我們運行以下代碼的時候:
| 1 2 3 | x = [1,2,3] for elem in x: ?... |
實際調用過程如下:
?
當我們反向編譯這段代Python碼的時候,可以發現它顯示調用了?GET_ITER,本質上跟調用iter(x)一樣,而FOR_ITER指令相等于調用next()方法來獲取每個元素。
>>> import dis
>>> x = [1,2,3]
>>> dis.dis('for _ in x: pass')
??1 ??????????0 SETUP_LOOP ?????????????12 (to 14)
??????????????2 LOAD_NAME ???????????????0 (x)
??????????????4 GET_ITER
????????>> ???6 FOR_ITER ????????????????4 (to 12)
??????????????8 STORE_NAME ??????????????1 (_)
?????????????10 JUMP_ABSOLUTE ???????????6
????????>> ??12 POP_BLOCK
????????>> ??14 LOAD_CONST ??????????????0 (None)
?????????????16 RETURN_VALUE
迭代器(Iterators)
那么什么是迭代器呢?任何具有__next__()方法的對象都是迭代器,對迭代器調用next()方法可以獲取下一個值。而至于它使如何產生這個值的,跟它能否成為一個迭代器并沒有關系。所以迭代器本質上是一個產生值的工廠,每次向迭代器請求下一個值,迭代器都會進行計算出相應的值并返回。
迭代器的例子很多,例如,所有itertools模塊中的函數都會返回一個迭代器,有的還可以產生無窮的序列。
有的函數根據有限序列中生成無限序列:
| 2 3 4 5 6 7 8 9 10 | >>> from itertools import cycle >>> colors = cycle(["red","white","blue"]) >>> next(colors) "red" >>> next(colors) "white" >>> next(colors) "blue" >>> next(colors) "red" |
有的函數根據無限序列中生成有限序列:
>>> from itertools import islice
>>> colors = cycle(['red', 'white', 'blue'])???? # infinite
>>> limited=islice(colors,0, 4)????????? ??# finite
>>> for x in limited:????????????????# so safe to use for-loop on
...????????????print(x)
red
white
blue
Red
為了更好的理解迭代器的內部結構,我們先來定義一個生成斐波拉契數的迭代器:
>>> class fib:
...???????????? def __init__(self):
...?????????????????? self.prev = 0
...?????????????????? self.curr = 1
...
...???????????? def __iter__(self):
...?????????????????? return self
...
...???????????? def __next__(self):
...?????????????????? value = self.curr
...?????????????????? self.curr += self.prev
...?????????????????? self.prev = value
...?????????????????? return value
...
>>> f = fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
注意這個類既是可迭代的 (因為具有__iter__()方法),也是它自身的迭代器(因為具有__next__()方法)。
迭代器內部狀態保存在當前實例對象的prev以及cur屬性中,在下一次調用中將使用這兩個屬性。每次調用next()方法都會執行以下兩步操作:
修改狀態,以便下次調用next()方法
計算當前調用的結果
比喻:從外部來看,迭代器就像政府工作人員一樣,沒人找他辦事的時候(請求值),工作人員就閑著,當有人來找他的時候(請求值),工作人員就會忙一會,把請求的東西找出來交給請求的人。忙完之后,又沒事了,繼續閑著。
生成器
生成器其實就是一種特殊的迭代器。它shi一種更為高級、更為優雅的迭代器。
使用生成器讓我們可以以一種更加簡潔的語法來定義迭代器。
讓我們先明確以下兩點:
任意生成器都是迭代器(反過來不成立)
任意生成器,都是一個可以延遲創建值的工廠
下面也是一個生成斐波那契序列的工廠函數,不過是以生成器的方式編寫的:
生成器的類型
在Python中兩種類型的生成器:生成器函數以及生成器表達式。生成器函數就是包含yield參數的函數。生成器表達式與列表解析式類似。
?
?
?
總結
以上是生活随笔為你收集整理的Python练习 | Python 可迭代对象 迭代器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV | Laplacian算子
- 下一篇: Python练习 | Python之图像