在使用python的過程中,很容易混淆如下幾個關聯的概念:
1.容器(container)
2.可迭代物件(iterable)
3.迭代器(iterator)
4.生成器(generator)
5.生成器表示式
6. 解析式
它們之間的關係如下表所示:
容器是用來儲存元素的一種資料結構,它支援隸屬測試,容器將所有資料儲存在記憶體中,在python中典型的容器有:
list, deque, …
set,frozesets,…
dict, defaultdict, ordereddict, counter, …
tuple, namedtuple, …
str容器相對來說很好理解,因為你可以把它當成生活中的箱子、房子、船等等。
一般的,通過判斷乙個物件是否包含某個元素來確定它是否為乙個容器。例如:
字典容器通過檢查是否包含鍵來進行判斷:
字串通過檢查是否包含某個子 串來判斷:
注意:並非所有的容器都是可迭代物件。
可迭代物件
正如前面所提到的,大部分容器都是可迭代的,但是還有其他一些物件也可以迭代,例如,檔案物件以及管道物件等等,容器一般來說儲存的元素是有限的,同樣的,可迭代物件也可以用來表示乙個包含有限元素的資料結構。
可迭代物件可以為任意物件,不一定非得是基本資料結構,只要這個物件可以返回乙個iterator。聽起來可能有點費解,但是可迭代物件與迭代器之間有乙個顯著的區別。先看下面的例子
注意:可迭代的類中,一般實現以下兩個方法,__iter__()以及__next()__方法,__iter__()方法返回self。
當我們執行以下**的時候:
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模組中的函式都會返回乙個迭代器,有的還可以產生無窮的序列。
有的函式根據有限序列中生成無限序列:
>>> 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)
redwhite
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__()方法)。
修改狀態,以便下次呼叫next()方法
計算當前呼叫的結果
比喻:從外部來看,迭代器就像**工作人員一樣,沒人找他辦事的時候(請求值),工作人員就閒著,當有人來找他的時候(請求值),工作人員就會忙一會,把請求的東西找出來交給請求的人。忙完之後,又沒事了,繼續閒著。
生成器
生成器其實就是一種特殊的迭代器。它shi一種更為高階、更為優雅的迭代器。
使用生成器讓我們可以以一種更加簡潔的語法來定義迭代器。
讓我們先明確以下兩點:
任意生成器都是迭代器(反過來不成立)
任意生成器,都是乙個可以延遲建立值的工廠
下面也是乙個生成斐波那契序列的工廠函式,不過是以生成器的方式編寫的:
生成器的型別
在python中兩種型別的生成器:生成器函式以及生成器表示式。生成器函式就是包含yield引數的函式。生成器表示式與列表解析式類似。
Python之可迭代物件 迭代器
python的特色之一是基於協議實現功能。比如改變乙個加號 的行為,在c 中需要操作符過載,在python中則是重寫 add 方法。為了描述可迭代物件和迭代器,python提供了兩個魔法方法,分別是 iter 和 next 又為了支援for.in.行為,牽扯進了 getitem 眾所周知使用for迴...
PYTHON 迭代器 可迭代物件
通過重複執行的 處理相似的資料集的過程,並且本次迭代的處理資料要依賴上一次的結果繼續往下做,上一次產生的結果為下一次產生結果的初始狀態,如果中途有任何停頓,都不能算是迭代。1 非迭代例子 loop 0 while loop 3 print hello world loop 1 2 迭代例子 loop...
python迭代 可迭代物件與迭代器物件
問題舉例 某軟體要求,從網路抓取各個城市的氣溫資訊,並依次顯示 北京 15 22 上海 18 23 如果一次抓取所有城市氣溫資訊再顯示,顯示第乙個城市的氣溫時會由很長的延時,並且浪費儲存空間,我們期望以 用時訪問 的策略,並且把所有城市的氣溫資訊封裝 到乙個物件裡,可用for語句進行迭代。來個栗子 ...