【一】迭代器
【1】介紹
迭代器即用來迭代取值的工具,而迭代是重復(fù)反饋的過程的活動
其目的通常是為了逼近所需的目標(biāo)或結(jié)果,每一次對過程的重復(fù)稱為一次”迭代“
而每一次迭代得到的結(jié)果會作為下一次迭代的初始值,單純的重復(fù)并不是迭代
while True:
msg = input('>>: ').strip()
print(msg)
# 獲取到返回值
num_list = [0, 1, 2, 3, 4, 5]
count = 0
while count < len(num_list):
# 每一次使用的索引位置就是上一次 +1 后的索引位置
print(num_list[count])
count += 1
【二】可迭代對象
【1】什么是可迭代對象
從語法上講,內(nèi)置有 __ iter __ 方法的對象都是可迭代對象
【2】八大基本數(shù)據(jù)類型
# 【1】數(shù)字類型 # 【1.1】整數(shù)類型 --- 不是 num = 1 print(num.__iter__) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 10, inprint(num.__iter__) AttributeError: 'int' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【1.2】浮點(diǎn)類型 --- 不是 num_float = 1.0 print(num_float.__iter__()) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 20, in print(num_float.__iter__) AttributeError: 'float' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【2】字符串類型 name = 'chosen' print(name.__iter__) # print(name.__iter__()) # # 【3】布爾類型 is_right = False print(is_right.__iter__) ''' Traceback (most recent call last): File "E:PythonProjects迭代器.py", line 37, in print(is_right.__iter__) AttributeError: 'bool' object has no attribute '__iter__'. Did you mean: '__str__'? ''' # 【4】列表類型 name_list = [1, 2, 3] print(name_list.__iter__) # print(name_list.__iter__()) # # 【5】字典類型 info_dict = {"name": "chosen"} print(info_dict.__iter__) # print(info_dict.__iter__()) # # 【6】元祖類型 num_tuple = (1,) print(num_tuple.__iter__) # print(num_tuple.__iter__()) # # 【7】集合類型 num_set = {1} print(num_set.__iter__) # print(num_set.__iter__()) #
【3】總結(jié)
非可迭代對象
整數(shù)類型
浮點(diǎn)類型
布爾類型
可迭代類型
字符串類型
列表類型
字典類型
元組類型
集合類型
【三】迭代器對象
【1】什么是迭代器對象
調(diào)用obj.__iter__()方法返回的結(jié)果就是一個(gè)迭代器對象(Iterator)。
迭代器對象是內(nèi)置有 iter 和 next 方法的對象,打開的文件本身就是一個(gè)迭代器對象
執(zhí)行迭代器對象.iter()方法得到的仍然是迭代器本身
而執(zhí)行迭代器.next()方法就會計(jì)算出迭代器中的下一個(gè)值。
迭代器是Python提供的一種統(tǒng)一的、不依賴于索引的迭代取值方式,只要存在多個(gè)“值”,無論序列類型還是非序列類型都可以按照迭代器的方式取值
【2】八大基本數(shù)據(jù)類型
# 【1】字符串類型 name_str = 'chosen' name_iter = name_str.__iter__() name_iter_two = iter(name_str) print(name_iter) print(name_iter_two) ## print(name_iter.__next__()) # c print(next(name_iter)) # h # 【2】列表類型 name_list = [1, 2, 3] name_list_iter = iter(name_list) print(name_list_iter) # print(name_list_iter.__next__()) # 1 print(next(name_list_iter)) # 2 # 【3】字典類型 info_dict = {"name": "chosen", "age": 18} info_dict_iter = iter(info_dict) print(info_dict_iter) # print(info_dict_iter.__next__()) # name print(next(info_dict_iter)) # age # 【4】元祖類型 num_tuple = (1, 2) num_tuple_iter = iter(num_tuple) print(num_tuple_iter) # print(num_tuple_iter.__next__()) # 1 print(next(num_tuple_iter)) # 2 # 【5】集合類型 num_set = {1, 2, 3} num_set_iter = iter(num_set) print(num_set_iter) # print(num_set_iter.__next__()) # 1 print(next(num_set_iter)) # 2
【3】總結(jié)
# 具有 __iter__() 和 __next__() 的對象就是迭代器對象 # 在八大基本數(shù)據(jù)類型中 # 除了 整數(shù)、浮點(diǎn)數(shù)、布爾 # 其他的都是迭代器對象 # 迭代器對象一定是可迭代對象 # 可迭代對象是 具有 __iter__() 的對象 ---> 生成一個(gè)可迭代對象 # 迭代器對象是 具有 __iter__() 和 __next__() 的對象 --> 調(diào)用上面可迭代對象的 next 方法
【四】迭代器的優(yōu)缺點(diǎn)
【1】優(yōu)點(diǎn)
為序列和非序列類型提供了一種統(tǒng)一的迭代取值方式
不使用索引進(jìn)行取值
取到值的時(shí)候會保存到當(dāng)前的狀態(tài),下一次從這個(gè)位置開始向下取值
【2】缺點(diǎn)
除非取盡,否則無法獲取迭代器的長度
只能取下一個(gè)值,不能回到開始,更像是’一次性‘的,迭代器產(chǎn)生后的唯一目標(biāo)就是重復(fù)執(zhí)行next方法直到值取盡,否則就會停留在某個(gè)位置,等待下一次調(diào)用next;
若是要再次迭代同個(gè)對象,你只能重新調(diào)用iter方法去創(chuàng)建一個(gè)新的迭代器對象,如果有兩個(gè)或者多個(gè)循環(huán)使用同一個(gè)迭代器,必然只會有一個(gè)循環(huán)能取到值。
【五】什么是生成器
通過生成器,可以逐個(gè)生成序列中的元素,而無需一次性生成整個(gè)序列
生成器在處理大數(shù)據(jù)集時(shí),具有節(jié)省內(nèi)存、提高效率的特點(diǎn)。
# 假設(shè)一個(gè)數(shù)據(jù)庫里 表里面存了1億條數(shù)據(jù) # 讀數(shù)據(jù)時(shí)---> 使用 read() 內(nèi)存會直接爆滿導(dǎo)致電腦卡死 # 使用生成器--->一次取100行進(jìn)行處理 ---->再取100行進(jìn)行處理,以此類推
【六】生成器的創(chuàng)建方式
【1】列表推導(dǎo)式
使用列表推導(dǎo)式時(shí),可以將列表推導(dǎo)式的方括號改為圓括號,即可創(chuàng)建一個(gè)生成器。
# 列表生成式生成列表 start_list = [x * 2 for x in range(5)] print(start_list) # [0, 2, 4, 6, 8] # 將列表改成元祖,看起來像元祖推導(dǎo)式,其實(shí)是一個(gè)生成器對象 G = (x * 2 for x in range(5)) print(G) #at 0x000001873491CC80> # 生成器對象可以強(qiáng)轉(zhuǎn)成列表 print(list(G)) # [0, 2, 4, 6, 8]
【2】yield關(guān)鍵字
使用yield關(guān)鍵字定義一個(gè)生成器函數(shù)時(shí),生成器函數(shù)中的yield語句會暫停函數(shù)執(zhí)行并返回一個(gè)值,下一次調(diào)用該函數(shù)時(shí)會繼續(xù)執(zhí)行并返回下一個(gè)值。
def my_generator():
yield 1
yield 2
yield 3
g = my_generator()
print(next(g)) # 輸出:1
print(next(g)) # 輸出:2
print(next(g)) # 輸出:3
【七】生成器案例
def eater():
print('開始吃飯 ovo ')
while True:
food = yield
print(f'得到的食物是 :>>>> {food}, 開始吃飯嘍 :>>>> {food}')
【1】調(diào)用函數(shù)
res = eater() print(res) #print(res.__next__()) # 打印開始吃飯 # None 原因就是在生成器內(nèi)部的 yield 中沒有返回值 print(res.__next__()) # 打印 得到的食物是 :>>>> None, 開始吃飯嘍 :>>>> None # None 原因就是在生成器內(nèi)部的走完了上面的 又回到了 yield 中結(jié)果 yield 沒有返回值
【2】向生成器中傳值
res = eater() print(res) #print(res.__next__()) res.send("魚香肉絲") #得到的食物是 :>>>> 魚香肉絲, 開始吃飯嘍 :>>>> 魚香肉絲 # 想yield 傳值并且讓生成器向下走一下 print(res.__next__()) #得到的食物是 :>>>> None, 開始吃飯嘍 :>>>> None print(res.send("宮保雞丁")) #得到的食物是 :>>>> 宮保雞丁, 開始吃飯嘍 :>>>> 宮保雞丁 #None
【八】裝飾器 + 生成器
def init_iter(func):
# func 我的生成器函數(shù)
def inner(*args, **kwargs):
# g 得到的生成器對象
g = func(*args, **kwargs)
# 調(diào)用自己生成器向下走
next(g)
# 走回來的返回值返回出去
return g
return inner
@init_iter
def eater():
print('開始吃飯 ovo ')
while True:
food = yield
print(f'得到的食物是 :>>>> {food}, 開始吃飯嘍 :>>>> {food}')
res = eater()
res.send("魚香肉絲")
res.send("宮保雞丁")
【九】生成器內(nèi)部修改可變數(shù)據(jù)類型
def init_iter(func):
# func 我的生成器函數(shù)
def inner(*args, **kwargs):
# g 得到的生成器對象
g = func(*args, **kwargs)
# 調(diào)用自己生成器向下走
next(g)
# 走回來的返回值返回出去
return g
return inner
@init_iter
def eater():
print('開始吃飯 ovo ')
food_list = []
while True:
food = yield
food_list.append(food)
print(f'得到的食物是 :>>>> {food}, 開始吃飯嘍 :>>>> {food}')
print(f'當(dāng)前后廚已經(jīng)做好了 :>>>> {food_list}')
res = eater()
res.send("魚香肉絲")
res.send("宮保雞丁")
# 輸出結(jié)果:
開始吃飯 ovo
得到的食物是 :>>>> 魚香肉絲, 開始吃飯嘍 :>>>> 魚香肉絲
當(dāng)前后廚已經(jīng)做好了 :>>>> ['魚香肉絲']
得到的食物是 :>>>> 宮保雞丁, 開始吃飯嘍 :>>>> 宮保雞丁
當(dāng)前后廚已經(jīng)做好了 :>>>> ['魚香肉絲', '宮保雞丁']
【十】yield + next搭配著使用
def my_range(start, stop, step):
'''
:param start: 0
:param stop: 5
:param step: 1
'''
print("start")
while start < stop:
yield start
start += step
print("end")
res = my_range(0, 5, 1)
print(res) #
print(res.__next__()) # 0
print(res.__next__()) # 1
print(res.__next__()) # 2
print(res.__next__()) # 3
print(res.__next__()) # 4
# 這里會報(bào)錯(cuò) ---》 把我掏空了 --- 沒有可迭代的值可以被獲取了
print(res.__next__()) # StopIteration
def init_iter(func):
def inner(*args, **kwargs):
try:
generator = func(*args, **kwargs)
next(generator)
return generator
except StopIteration:
pass
return inner
def range_(start, stop, step):
while start < stop:
yield start
start += step
# for 循環(huán)內(nèi)部做了異常捕獲
for i in range_(0,5,1):
print(i)
def my_range(start, stop, step):
def range_(start, stop, step):
while start < stop:
yield start
start += step
res = range_(start, stop, step)
while True:
try:
print(res.__next__())
except StopIteration:
break
res = my_range(start=1, stop=5, step=1)
res
#輸出結(jié)果
0
1
2
3
4
1
2
3
4
鏈接:https://www.cnblogs.com/chosen-yn/p/18143555
-
字符串
+關(guān)注
關(guān)注
1文章
594瀏覽量
23023 -
Next
+關(guān)注
關(guān)注
0文章
8瀏覽量
6362 -
迭代器
+關(guān)注
關(guān)注
0文章
45瀏覽量
4580
原文標(biāo)題:【十】yield + next搭配著使用
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
小安派BW21-CBV-Kit入門教程之驅(qū)動ILI9341 TFT顯示屏
小安派BW21-CBV-Kit入門教程之MPU6050 IMU零點(diǎn)檢測
NEXT(Near-End Crosstalk,近端串?dāng)_)
小安派BW21-CBV-Kit入門教程之主機(jī)模式對Arduino UNO發(fā)送數(shù)據(jù)
小安派BW21-CBV-Kit入門教程之主機(jī)模式讀取Arduino UNO從機(jī)
小安派BW21-CBV-Kit入門教程之OLED顯示
小安派BW21-CBV-Kit入門教程之LCD屏顯示數(shù)據(jù)
Google Cloud Next 2025大會亮點(diǎn)回顧
HarmonyOS Next V2 @Monitor 和@Computed
HarmonyOS Next V2 @Event
小安派BW21-CBV-Kit入門教程之讀取DHT溫濕度傳感器
小安派BW21-CBV-Kit入門教程之超聲波測距
小安派BW21-CBV-Kit入門教程:中斷控制LED
BW21-CBV-Kit快速入門之Arduino環(huán)境搭建

yield + next搭配著使用
評論