python:容器、迭代器、生成器 簡單介紹

python:容器、迭代器、生成器 簡單介紹

python提供了多種數據類型來存放數據項。
以前已經介紹了幾個python中經常使用的容器,分別是列表list、元組tuple、字典dict和集合set。
這幾種數據結構在Python中是很是重要的部分,尤爲是各自的特性部分。掌握好了,處理數據的時候會很方便。java

容器 container

容器是一種把多個元素組織在一塊兒的數據結構。容器中的元素能夠經過for循環逐個地迭代獲取,也能夠經過in關鍵字來判斷元素是否在容器中。
在Python中,常見的容器對象:python

  • list、dequeue...
  • set、frozenset...
  • dict、defaultdict、OrderDict...
  • tuple、namedtuple...
  • str
  • file
引用一張以前從其餘博文上截的圖,以爲很形象,很好的解釋了之間的關係。不過很差意思,出處找不到了
clipboard.png

大部分容器都提供了某種方式能夠獲取到其中的每個元素,可是這並非容器自己提供的功能,而是可迭代對象賦予了容器這種能力。算法

迭代 iteration

什麼叫迭代?

若是給定一個list或者tuple數據類型變量,咱們能夠經過for循環來遍歷這個list或者tuple,那這種遍歷能夠成爲迭代。編程

  • 在java中,迭代list是經過下標index來完成的,例如:
for (i=0;i<param.length;i++){
    val = param[index];
}
# 剛好最近在從新撿起java
  • 在Python中,迭代是經過for...in 循環完成的。Python中的for循環能夠用在string、list、tuple、dict等其餘可迭代對象上。例如:
>>> d = {'a':1,'b':2,'c':3}  
>>> for key in d:     # dict
...     print(key)
...
a
b
c
>>> for ch in 'AB':   # str 
... print(ch)
...
A
B

因此,當咱們使用for循環時,咱們不太去關心做用的對象到底是list、tuple仍是其餘數據類型,只要做用於一個可迭代對象上,for循環就能夠正常運行。
so...數據結構

可迭代對象 iterable

可迭代對象,Iterable。可直接使用for循環的對象統稱爲可迭代對象。
那麼你可能會問,如何去判斷一個對象是不是可迭代對象呢?
ans:方法是經過引入collections模塊中的Iterable類型來判斷,同時使用isinstance()。函數

>>> from collections import Iterable    # 引入Iterable
>>> isinstance('abc',Iterable)
True
>>> isinstance(123,Iterable)
False
  • 補充一小點知識,如何經過for循環,把list的索引和值都讀出來呢?使用 enumerate() 來完成。

Python內置的enumerate()枚舉函數能夠把一個list編程索引-元素對,這樣就能夠在for循環中同時迭代索引和元素自己。以下:spa

>>> l=['a','b','c','d']
>>> for ind,val in enumerate(l):
...        print("%d %s"%(ind,val))
...
0 a
1 b
2 c
3 d

迭代器 iterator

能夠被next()函數調用並不斷返回下一個值的對象爲迭代器,iterator。
Python中的iterator對象是一個帶狀態的對象,表示的是一個數據流,他實現了以下兩個方法:code

  • __iter__:返回迭代器自己;
  • __next__:返回容器的下一個元素;

雖然list、dict、tuple是能夠迭代的對象,但不是迭代器。
可是可迭代對象實現了__iter__方法,該方法返回一個迭代器對象。對象

如何建立迭代器

  • iter()

如何建立一個可迭代對象?經過調用iter()方法實現,以下圖所示:blog

clipboard.png

  • next()

可迭代對象能夠被next()調用並不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。以下:

clipboard.png

咱們能夠想象迭代器數據流看作是一個有序的序列,可是不能提早知道序列到底有多長,只能不斷經過next()函數來實現讀取下一個數據。
因此Iterator的計算是一個惰性的,至於在須要返回下一個數據時,他纔會計算。

Iterator甚至能夠表示一個無限大的數據流,例如全體天然數。而使用list是永遠不可能存儲全體天然數的。

生成器 generator

生成器是一種特殊的迭代器。
一個函數只返回一次,但一個生成器能暫停執行並返回一箇中間的結果,當生成器的next()方法被調用時,它就又會從離開的地方繼續運行,實現一邊循環一邊計算的機制,這種就稱爲生成器generator

生成器建立方法

生產器的建立方法有兩種:一是生成器表達式;二是yield關鍵字。

  • 生成器表達式

    直接上例子啦:注意一點就是,生成器最外層的是「()」,list最外成是「[]」。

>>> g = ( x*x for x in range(10) )
>>> g
<generator object <genexpr> at 0x010B3690>
# 使用next()來得到generator的下一個返回值
>>> next(g)
0
>>> next(g)
1
# g保存的是算法,每次調用next(g),就計算出下一個元素的值,直到沒有更多元素時拋錯
  • yield關鍵字

若是一個函數定義中包含yield關鍵字,那麼這個函數就再也不是一個普通的函數,而是一個generator。
例如,用函數實現斐波那契數列,咱們可使用以下方法:

def fib(max):
    n,a,b = 0,0,1
while n < max:
    print(b)
    a,b=b,a+b
    n = n + 1
    return 'done'

其中,fib()定義了斐波那契的推算規則。
那咱們能夠把fib()變成generator。以下:

def fib():
    prev,curr = 0,1
    while True:
        yield curr
        prev,curr = curr , curr + prev

上述函數體中,返回值不是return關鍵字了,而是yield,函數返回值是一個生成器對象。
當執行f=fib()時返回的是一個生成器對象,此時函數體中的代碼不會執行,只有顯示或隱式調用next()的時候纔會真正執行裏面的代碼。
在每次調用next()的時候執行,遇到yield語句返回,再次執行時,從上次返回的yield語句處繼續執行。
咱們能夠經過一個例子演示說明:

>>> def odd():
...     print('step1')
...     yield 1
...     print('step2')
...     yield 2
...     print('step 3')
...     yield 3
...
>>> o = odd()
>>> next(o)
step1
1
>>> next(o)
step2
2

好啦,今天就寫到這~


❤ thanks for watching, keep on updating...

相關文章
相關標籤/搜索