python 迭代器與生成器即迭代協議的特別說明

2021-08-01 16:47:36 字數 2605 閱讀 3174

python 中抽象程度更高,直接在語言層面支援對容器進行迭代。c++ 中在泛型演算法和容器之間還需要借助中間層迭代器來粘合。

可迭代的是兩類物件:

1、包含 __iter__ 方法的。

2、包含 __getitem__ 方法的。比如 str 物件就沒有 __iter__ 方法,但是一樣能夠迭代。

另外,判斷是否只能迭代一次的:

iter(obj) == obj

相等表示 obj 是自身的迭代器,所以只能迭代一次。

不等表示每次跌倒時,實際都是生成乙個臨時物件來操作,所以能夠迭代多次。

生成器還包含三個特殊的方法:

send(), close(), throw().

receive = yield value

...g.send(1)

呼叫 send  方法之後,也是在進入生成器並在 yield 停止,返回 yiled 後邊的表示式,這一點同 next 函式一樣。

不同之處在於,在send 為下一次進入生成器時,傳入乙個值。**片段中 receive 是在下一次進入生成器時賦值為send傳入的值。

下一次生成器再執行,第一條語句是 receive = 1

close() 方法用來關閉生成器,之後再拿關閉之後的生成來迭代直接丟擲 stopiteration 異常。

throw() 方法用來顯示的再進入到迭代器時丟擲乙個異常,如果該異常不能**獲,程式直接結束;能捕獲,則關注捕獲的地方。如果捕獲的地方在生成器的內部,生成器有效;如果是生成器外部捕獲,相當於由非 yield 跳出的生成器,生成器不能再迭代了。

總結:非yield的跳出,如 return,break 等跳轉語句或丟擲異常e,在跳出了之後,立即丟擲 stopiteration 或者異常e。

有了迭代協議,可以更方便的表達類似的概念,而不用關注底層的實現(抽象的好處,有選擇性的忽略,降低問題的複雜度)。

1、函式的可變引數包,表示呼叫時,最終打包成 tuple 元祖。

l = list(range(3))

s = "hello"

d = dict(x = 1, y = 2, z = 3)

def gen():

yield 1

yield 2

yield 3

def func(*a):

print(type(a))

print(a)

func(*d) #字典

func(*gen()) #生成器

func(*l) #列表

func(*s) #字串

輸出如下,#呼叫時,* + 可迭代物件:表示將可呼叫物件解包成位置引數。不論引數是普通容器還是生成器,只要是可迭代的,皆可以在呼叫時解包。匹配掉前邊的位置引數和已命名的引數,剩下的打包進 tuple 作為可變引數。

('x', 'y', 'z')

(1, 2, 3)

(0, 1, 2)

('h', 'e', 'l', 'l', 'o')

2、關鍵字引數,表示呼叫時,最終打包成 dict 字典。

命名引數這裡指的是呼叫時,按照 引數名 = value 的形成進行呼叫,且引數名稱出現在函式定義的列表中的引數。如下邊的函式 fund 中的引數 y,在字典解包時,傳入的值為2.匹配掉已命名的關鍵字引數,剩下的打包進dict.

d = dict(x = 1, y = 2, z = 3)

def fund(y = 0, **a):

print(type(a))

print(a)

fund(**d) #字典

輸出如下:

沒啥好說的,** + 字典表示字典解包成 key = value 的關鍵字引數包(鍵為 "key" 字串)。 'y' 匹配給了命名引數。

3、聚合賦值,表示賦值左邊的帶 * 物件打包成 list 列表。

a = 1

b = 2

c = 3

def gen():

yield 1

yield 2

yield 3

x, *y = a, b, c #a, b, c 等價於 (a, b, c)是個元祖

print(type(x),x)

print(type(y), y)

x, *y = dict(a = 1, b = 2, c = 3)

print(type(x),x)

print(type(y), y)

x, *y = gen()

print(type(x),x)

print(type(y), y)

輸出如下:

1

[2, 3]

a['b', 'c']

1[2, 3]

同1一樣,建立在迭代協議之上,只要賦值右邊是可迭代的,賦值左邊的 *y 表示按照 list 列表打包。

python中生成式和生成器 迭代器與可迭代

標籤 python 比如a 1,2,3 如果想生成乙個b裡面存的是a的2倍,則可以使用 2 i for i in a 上面通過生成式雖然可以生成乙個列表,但是如果我們列表過於大,可能一次儲存不下,所以便有了生成器這個說法。生成器你可以把他看做乙個方法,每次使用一下它,他就能幫你按照你的規則生成乙個數...

Python生成器與迭代器

生成器只有在用的時候會出現在記憶體中,對比列表全部存在記憶體中,減少了記憶體占用 next 函式 依次取生成器的值 s x 2 for x in range 1000 中括號是列表解析,小括號表示生成一系列值,就是生成器 s at 0x7fa20aa8b048 print next s 用next ...

python 迭代器與生成器

迭代器和生成器 print 1 in 1,2,3 print 1 not in 1,2,3 print 4 in print 4 not in 1,2,3 print x not in dlkjfxfei 可迭代物件 iterable 可以被next 函式呼叫並不斷返回下乙個值 知道沒有資料時丟擲s...