python notice9 迭代器和生產器

2022-08-09 03:57:09 字數 3890 閱讀 5118

一、迭代器

可以進行for迴圈的都是可迭代物件,常見的可迭代物件:str、list、tuple、dict、set、range、f(檔案),它們都遵循可迭代協議。  

s = "

小黑人"

for el in

s:

print(el)

iterable:可迭代物件,內部包含__iter__()函式。

iterator:迭代器,內部包含__iter__同時還包含__next__()。

想要檢視某資料型別是否為可迭代物件或者迭代器,可以通過dir()函式檢視時候包含__iter__或者__iter__和__next()__。

通過__iter__()可以獲取到物件的迭代器,使用迭代器中的__next__()來獲取迭代器中的元素。

s = "

小黑人"

c = s.__iter__() #

獲取迭代器

print(c.__next__()) #

使用迭代器進行迭代,獲取乙個元素,小

print(c.__next__()) #

黑print(c.__next__()) #

人print(c.__next__()) #

stopiteration

迭代器特點:

1.節省記憶體。

2.惰性機制。

3.只能向下執行,不能反覆。

補充:for迴圈機制

s = "

小黑人"

c = s.__iter__

()while

true:

try:

i = c.__next__

()

print

(i)

except

stopiteration:

break

二、生成器

生成器實質就是迭代器。獲取生成器有三種方法:生成器函式、推導式獲取生成器、通過資料轉換獲取生成器。

1.生成器函式

def

func():

print("

小黑人"

)

yield 114 #

把函式中return改成yield,這個函式就是生成器函式

print("

小黑人不黑")

yield 3114 #

原來時0114,但是會報錯,0不能打頭,語法不支援。

ret =func()

print

(ret)

ss = ret.__next__

()print

(ss)

ss = ret.__next__

()print

(ss)

結果:小黑人

114小黑人不黑

3114

注:執行這個函式時,就不是函式的執行,而是獲取這個生成器。生成器本質時迭代器,可以通過__next__()來執行生成器。

yield和return效果一樣,遇到return是直接停止執行函式,而yield是分段來執行乙個函式(當內容多時,一次性全部輸出,會佔大量記憶體;而用yield時,next一此就輸出乙個,不佔記憶體)。當程式執行完最後乙個yield,後面繼續進行__next__()時程式會報錯。

生成器也可以用for迴圈獲取內部元素。因為生成器就是迭代器,迭代器為可迭代物件,故可以進行for迴圈。 

補充send:

1.send()和__next__()一樣,都可以讓生成器執行到下乙個yield;

2.send可以給上乙個yield的位置傳遞值,但不能給最後乙個yield傳值,同時在第一次執行生成器**時不能使用send()。

def

func():

print("

小黑人"

) a = yield 114 #

把函式中return改成yield,這個函式就是生成器函式

print("a="

,a)

yield 3114 #

原來時0114,但是會報錯,0不能打頭,語法不支援。

ret =func()

ss = ret.__next__

()print

(ss)

ss = ret.send("

小黑人不黑")

print

(ss)

結果:小黑人

114a=小黑人不黑

3114

2.生成器表示式

列表、字典、集合都有推導式,元組沒有推導式。

列表推導式:[結果 fof 變數 in 可迭代物件 if 篩選]

字典推導式:  結果:key:value

集合推導式:  結果:key

eg:列表推導式:list = [結果 for in 可迭代物件 if 條件]

lst = ["

小黑人%s

" % i for i in

range3)]

print

(lst)

結果:[

'小黑人0

', '

小黑人1

', '

小黑人2

']

列表推導式**簡單,但是出現錯誤之後不易排查。

生成器表示式和列表推導式語法一樣,只是把換成()。

lst =("

小黑人%s

" % i for i in

range(0))

print

(lst)

結果:at 0x0000017602b9a2a0>

生成器表示式和列表推導式區別:

1.列表推導式比較耗記憶體,一次性載入,生成器表示式幾乎不佔記憶體,使用時才分配和使用記憶體。

2.得到的值不一樣。列表推導式得到的是乙個列表,生成器表示式獲取的是乙個生成器。

注:生成器有惰性機制:生成器只有在方位的時候才有值。說白了,找它要才會給值,不找它要,它是不會執行的。

def

func():

print(111)

yield 222g = func() #

生成器g

g1 = (for i in g) #

生成器g1,但是g1的資料**於g

g2 = for i in g1) #

生成器g2,但是g2的資料**於g1

print(list(g)) #

獲取g中的資料,這時func()才會被執行,列印111,獲取222,g完畢

print(list(g1)) #

獲取g1中的資料,g1的資料**是g,但g已經取完,沒有資料了。

print(list(g2)) #

和g1相同

測試題

def

add(a,b):

return a +b

deftest():

for r_i in range(4):

yield

r_ig =test()

for n in [2,10]:

g = (add(n,i) for i in

g)

'''展開一層:g = (add(n,i) for i in add(n,i) for i in g),

展開第二層:g = (add(n,i) for i in add(n,i) for i in test()),

兩個n在取值時不可能不同,取值時為10。

'''print

(g)print(list(g)) #

惰性機制,不到最後不會拿值。

結果:at 0x000001c5c0c6a408>[20, 21, 22, 23]

迭代器和反向迭代器,常量迭代器和非常量迭代器

迭代器的型別共有4種 iiterator,const iterator,reverse iterator,const reverse iterator include include include include using namespace std int main include inclu...

Python基礎9,迭代器和生成器

1,迭代器 dict1 print dir dict1 迭代 重複同乙個動作 list1 1 2,3 4,5 print dir list1 for i in list1 print i index 0while index len list1 print list index index 1從可迭...

迭代(iterable)和迭代器

任何可迭代物件都可以作用於for迴圈,包括我們自定義的資料型別,只要符合迭代條件,就可以使用for迴圈 d 對dict迭代 for k,v in d.items 如果要同時迭代key和value,可以用for k,v in d.items print k,v 預設情況下,dict迭代的是key 如果...