python之迭代器和生成器

2021-09-03 02:01:20 字數 3898 閱讀 9042

要將生成器,先講一下列表生成式。

列表生成式

如果我們要建立乙個有規律的列表,比如說1-10:

# list1 = [1,2,3,4,5,6,7,8,9,10]

list1 = [i for i in range(1,11)] # 列表生成式

print(list1)

print(list1[2])

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

3

如果我們想要的是[1,4,9,16…]呢?我們也可以用列表生成式很方便的得到:

list1 = [x * x for x in range(1,11)]
甚至我們可以定義乙個對應函式f,於是有:

list1 = [f(x) for x in range(1,11)]
生成器

我們可以發現,第一段**中,用列表生成式生成了list1,並且可以用index來訪問其中的值。那麼我們將方括號改為圓括號試一下:

list1 = (x for x in range(1,11))

print(list1)

print(list1[2])

at 0x02f26470>

traceback (most recent call last):

file "listcomprehensions.py", line 6, in print(list1[2])

typeerror: 'generator' object is not subscriptable

我們發現,list1不再是列表,而是乙個生成器物件(generator object),並且不可以用下表來訪問,那我們改怎麼訪問呢?

list1 = (x for x in range(1,11))

print(list1)

for i in list1:

print(i)

我們可以用for迴圈來獲取每乙個值。

為什麼要使用生成器呢?通過列表生成式,我們可以直接建立乙個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立乙個包含100萬個元素的列表,不僅占用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素占用的空間都白白浪費了。

所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在python中,這種一邊迴圈一邊計算的機制,稱為生成器(generato

r)。

list1 = (x for x in range(1,11))

print(list1)

print(list1.__next__())

print(list1.__next__())

print(list1.__next__())

print("break...")

print(list1.__next__())

print(list1.__next__())

print(list1.__next__())

根據上面**,我們知道,生成器會記錄之前的狀態,即使我們中斷了,再次呼叫它的next方法時,依舊會繼續上次的執行。

注意生成器的兩點:

1.只有next方法,只能往前走,不能後退;

2.只能一步步前進,不能跨大步,不能用index訪問。

將函式改為生成器

def fib(x):

n,a,b = 0,1,1

while n < x:

print(a)

a, b = b, a + b

n += 1

上面的**可以輸出指定長度的斐波拉契數列,它離生成器只有一步之遙,下面我們就將其改為生成器。

def fib(x):

n,a,b = 0,1,1

while n < x:

# print(a)

yield a

a, b = b, a + b

n += 1

g = fib(10)

print(g)

for x in g:

print(x)

上面我們同樣可以輸出指定長度的數列。生成器的結束條件有三種:

1.遇到yield關鍵字

2.遇到return

3.函式執行完

import time

def consumer(name):

print("%s prepare to eat cake" % name)

while true:

cake = yield

print("cake [%s] is ate by [%s]" % (cake,name))

def producer(name):

c = consumer("rose")

c.__next__()

print("[%s] prepare to make cake..." % name)

for i in range(1,11):

time.sleep(1)

print("[%s] has made a cake[%s]" % (name,i))

c.send(i)

producer("jack")

可迭代物件的定義:

1.可以直接作用於for迴圈的資料型別,如list,str,tuple…

2.生成器,包括帶yield的生成器函式。

這些可直接作用於for迴圈的物件統稱為可迭代物件(iterable)

我們可以用isinstance來判斷是否是可迭代物件(collections快廢棄了)。

from collections import iterable

print(isinstance(,iterable)) # true

print(isinstance("abc",iterable)) # true

print(isinstance(10,iterable)) # false

print(isinstance((x for x in range(10)),iterable)) # true

迭代器的定義:可以被next()函式呼叫並不斷返回下乙個值的物件稱為迭代器。

注意:1.生成器一定是迭代器

2.迭代器一定是可迭代物件

3.可迭代物件不一定是迭代器(可以作用於for迴圈但是沒有next方法)

from collections import iterator

print(isinstance(,iterator)) # false

print(isinstance("abc",iterator)) # false

print(isinstance(10,iterator)) # false

print(isinstance((x for x in range(10)),iterator)) # true

將可迭代物件變為迭代器

我們可以使用iter方法將可迭代物件變為迭代器:

from collections import iterator

print(isinstance(iter(),iterator)) # true

print(isinstance(iter("abc"),iterator)) # true

iterator物件表示乙個資料流,可以不斷的用next方法獲取下乙個資料,但是我們無法獲取其長度,它的計算是惰性的,只有在需要時才會計算下乙個資料。

python之生成器和迭代器

迭代 遍歷挨個取元素 a 1,2,3,4,5,6 for i in a print i 1,2,3,4,5,6 可迭代物件 實現了迭代器的物件 在產生這個物件的類中定義了 iter 方法 迭代器 迭代器在類中實現了兩個物件 iter 方法 返回迭代器物件本身 next 方法 返回下乙個元素 這裡需要...

python之生成器和迭代器

生成器表示式 返回乙個物件,這個物件只有在需要的時候才產生結果 生成器函式 為什麼叫生成器函式?因為它隨著時間的推移生成了乙個數值佇列。一般的函式在執行完畢之後會返回乙個值然後退出,但是生成器函式會自動掛起,然後重新拾起急需執行,他會利用yield關鍵字關起函式,給呼叫者返回乙個值,同時保留了當前的...

PYTHON之迭代器和生成器

所謂迭代,就是乙個迴圈,厲遍資料結構 列表,字典,元組等 內元素的過程。字串,列表,字典,元組,集合都是可迭代物件。而迭代器是用與迭代操作 for迴圈 的物件。可迭代物件通過 iter 方法轉變成迭代器,迭代器可以通過next 方法不斷返回下乙個元素直至結束。迭代器的優勢在於它不像列表那樣會預先就把...