程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python3高級特性(五)之容器(container)

編輯:Python

目錄

容器(container)

迭代器(iterator)

生成器(generator)

生成器簡介

yield案例


容器(container)

容器是一種把多個元素組織在一起的數據結構,容器中的元素可以逐個地迭代獲取,可以用in, not in關鍵字判斷元素是否包含在容器中。

在Python中,常見的容器對象有:

1)      list, deque, ….

2)      set, frozensets, ….

3)      dict, defaultdict, OrderedDict, Counter, ….

4)      tuple, namedtuple, …

5)      str

容器比較容易理解,因為可以把它看作是一個盒子,裡面可以塞任何東西。從技術角度來說,當它可以用來詢問某個元素是否包含在其中時,那麼這個對象就可以認為是一個容器,比如 list,dict, set,tuples都是容器對象。

容器是一系列元素的集合,str、list、set、dict、file、sockets對象都可以看作是容器,容器都可以被迭代(用在for,while等語句中),因此他們被稱為可迭代對象。但凡是可以返回一個迭代器的對象都可稱之為可迭代對象,

迭代器(iterator)

那麼什麼迭代器呢?它是一個帶狀態的對象,能在你調用next()方法的時候返回容器中的下一個值,任何實現了__iter__和__next__()方法的對象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一個值,如果容器中沒有更多元素了,則拋出StopIteration異常,至於它們到底是如何實現的這並不重要。迭代器就是實現了工廠模式的對象,它在每次詢問要下一個值的時候給你返

生成器(generator)

生成器簡介

生成器算得上是Python語言中最吸引人的特性之一,生成器其實是一種特殊的迭代器,不過這種迭代器更加優雅。它不需要再像上面的類一樣寫__iter__()和__next__()方法了,只需要一個yiled關鍵字。

生成器一定是迭代器(反之不成立),因此任何生成器也是以一種懶加載的模式生成值。它特殊的地方在於函數體中沒有return關鍵字,函數的返回值是一個生成器對象,只有顯示或隱示地調用next的時候才會真正執行裡面的代碼。

生成器在Python中是一個非常強大的編程結構,可以用更少地中間變量寫流式代碼,相比其它容器對象它更能節省內存和CPU,當然它可以用更少的代碼來實現相似的功能。

yield案例

生成器對象是一個迭代器:但是它比迭代器對象多了一些方法,它們包括send方法,throw方法和close方法。這些方法,主要是用於外部與生成器對象的交互。

send方法有一個參數:該參數指定的是上一次被掛起的yield語句的返回值。

案例如下:

def MyGenerator():
    receive = yield 100
    print('extra' + str(receive))
    receive = yield 200
    print('extra' + str(receive))
    receive = yield 300
    print('extra' + str(receive))
gen = MyGenerator()
print(next(gen))  #也可以用:print(gen.send(None))
print("first")
print(gen.send(2))
print("second")
print(gen.send(3))
print("third")

輸出:100  first   extra2   200    second   extra3    300   third

注意,yield語句是最具魔力的表達式:這裡“yield 100”整體被視為一個表達式,send的內容會作為這個表達式的值,隨便左邊用什麼變量接收或者不接收,總之yield就是send進來的那個值。這個表達式變成send進來後的那個值之後,繼續往下執行,直到再次遇到yield,掛起。

如何啟動生成器呢?調用(gen.next()或gen.send(None))上面代碼的運行過程如下。

當調用gen.next()方法時:python首先會執行MyGenerator方法的yield 1語句。由於是一個yield語句,因此方法的執行過程被掛起,而next方法返回值為yield關鍵字後面表達式的值,即為100。

當調用gen.send(2)方法時:python首先恢復MyGenerator方法的運行環境。同時,將表達式(yield 100)的返回值定義為send方法參數的值,即為2。這樣,接下來value=(yield 100)這一賦值語句會將value的值設為2。繼續運行會遇到yield value語句,MyGenerator方法再次被掛起。同時,send方法的返回值為yield關鍵字後面表達式的值,也即value的值,為200。

當調用gen.send(3)方法時:首先恢復MyGenerator方法的運行環境。同時,將表達式(yield value)的返回值定義為send方法參數的值,即為3。這樣,接下來value=(yield 200)這一賦值語句會將value的值置為3。繼續運行,MyGenerator方法執行完畢。以此類推….

總的來說:

send方法和next方法唯一的區別,在執行send方法會首先把上一次掛起的yield語句的返回值通過參數設定,從而實現與生成器方法的交互。但是需要注意,在一個生成器對象沒有執行next方法之前,由於沒有yield語句被掛起,所以執行send方法會報錯。當然,下面的代碼是可以接受的:

gen = MyGenerator() 
print( gen.send(None) )

因為當send方法的參數為None時,它與next方法完全等價。但是注意,雖然上面的代碼可以接受,但是不規范。所以,在調用send方法之前,還是先調用一次next方法為好。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved