一、迭代器
可以進行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__
()
(i)
except
stopiteration:
break
二、生成器
生成器實質就是迭代器。獲取生成器有三種方法:生成器函式、推導式獲取生成器、通過資料轉換獲取生成器。
1.生成器函式
deffunc():
print("
小黑人"
)
yield 114 #
把函式中return改成yield,這個函式就是生成器函式
print("
小黑人不黑")
yield 3114 #
原來時0114,但是會報錯,0不能打頭,語法不支援。
ret =func()
(ret)
ss = ret.__next__
(ss)
ss = ret.__next__
(ss)
結果:小黑人
114小黑人不黑
3114
注:執行這個函式時,就不是函式的執行,而是獲取這個生成器。生成器本質時迭代器,可以通過__next__()來執行生成器。
yield和return效果一樣,遇到return是直接停止執行函式,而yield是分段來執行乙個函式(當內容多時,一次性全部輸出,會佔大量記憶體;而用yield時,next一此就輸出乙個,不佔記憶體)。當程式執行完最後乙個yield,後面繼續進行__next__()時程式會報錯。
生成器也可以用for迴圈獲取內部元素。因為生成器就是迭代器,迭代器為可迭代物件,故可以進行for迴圈。
補充send:
1.send()和__next__()一樣,都可以讓生成器執行到下乙個yield;
2.send可以給上乙個yield的位置傳遞值,但不能給最後乙個yield傳值,同時在第一次執行生成器**時不能使用send()。
deffunc():
print("
小黑人"
) a = yield 114 #
把函式中return改成yield,這個函式就是生成器函式
print("a="
,a)
yield 3114 #
原來時0114,但是會報錯,0不能打頭,語法不支援。
ret =func()
ss = ret.__next__
(ss)
ss = ret.send("
小黑人不黑")
(ss)
結果:小黑人
114a=小黑人不黑
3114
2.生成器表示式
列表、字典、集合都有推導式,元組沒有推導式。
列表推導式:[結果 fof 變數 in 可迭代物件 if 篩選]
字典推導式: 結果:key:value
集合推導式: 結果:key
eg:列表推導式:list = [結果 for in 可迭代物件 if 條件]
lst = ["小黑人%s
" % i for i in
range3)]
(lst)
結果:[
'小黑人0
', '
小黑人1
', '
小黑人2
']
列表推導式**簡單,但是出現錯誤之後不易排查。
生成器表示式和列表推導式語法一樣,只是把換成()。
lst =("小黑人%s
" % i for i in
range(0))
(lst)
結果:at 0x0000017602b9a2a0>
生成器表示式和列表推導式區別:
1.列表推導式比較耗記憶體,一次性載入,生成器表示式幾乎不佔記憶體,使用時才分配和使用記憶體。
2.得到的值不一樣。列表推導式得到的是乙個列表,生成器表示式獲取的是乙個生成器。
注:生成器有惰性機制:生成器只有在方位的時候才有值。說白了,找它要才會給值,不找它要,它是不會執行的。
deffunc():
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相同
測試題
defadd(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。
(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 如果...