Python中迭代器與生成器的用法
一、迭代器(foreach)
1、可迭代的對象
內(nèi)置有__iter__方法的都叫可迭代的對象。
Python內(nèi)置str、list、tuple、dict、set、file都是可迭代對象。
x = 1.__iter__ # SyntaxError: invalid syntax # 以下都是可迭代的對象 name = 'nick'.__iter__ print(type(name)) # 'method-wrapper'>
2、迭代器對象
執(zhí)行可迭代對象的__iter__方法,拿到的返回值就是迭代器對象。
只有字符串和列表都是依賴索引取值的,而其他的可迭代對象都是無法依賴索引取值的,只能使用迭代器對象。
- 內(nèi)置有
__iter__方法,執(zhí)行該方法會拿到迭代器本身。 - 內(nèi)置
__next__方法,執(zhí)行該方法會拿到迭代器對象中的一個值。
s = 'hello'
iter_s = s.__iter__()
print(type(iter_s)) # 'str_iterator'> iter_s為迭代器對象
while True:
try:
print(iter_s.__next__())
except StopIteration:
break
#hello3、迭代器有兩個基本的方法:iter() 和 next()。
s = 'hello'
iter_s = iter(s) # 創(chuàng)建迭代器對象
print(type(iter_s)) # iter_s為迭代器對象
while True:
try:
print(next(iter_s)) # 輸出迭代器的下一個元素
except StopIteration:
break
# hello4、for迭代器循環(huán)
可迭代對象可以直接使用常規(guī)for語句進行遍歷
for循環(huán)稱為迭代器循環(huán),in后必須是可迭代的對象。
#str
name = 'nick'
for x in name:
print(x)
#list
for x in [None, 3, 4.5, "foo", lambda: "moo", object, object()]:
print("{0} ({1})".format(x, type(x)))
#dict
d = {
'1': 'tasty',
'2': 'the best',
'3 sprouts': 'evil',
'4': 'pretty good'
}
for sKey in d:
print("{0} are {1}".format(sKey, d[sKey]))
#file
f = open('32.txt', 'r', encoding='utf-8')
for x in f:
print(x)
f.close()5、實現(xiàn)迭代器(__next__和__iter__)
把一個類作為一個迭代器使用需要在類中實現(xiàn)兩個方法 __iter__() 與 __next__() 。
- __iter__() 方法返回一個特殊的迭代器對象, 這個迭代器對象實現(xiàn)了 __next__() 方法并通過 StopIteration 異常標(biāo)識迭代的完成。
- __next__() 方法會返回下一個迭代器對象。
- StopIteration 異常用于標(biāo)識迭代的完成,防止出現(xiàn)無限循環(huán)的情況,在 __next__() 方法中我們可以設(shè)置在完成指定循環(huán)次數(shù)后觸發(fā) StopIteration 異常來結(jié)束迭代。
創(chuàng)建一個返回數(shù)字的迭代器,初始值為 1,逐步遞增 1,在 20 次迭代后停止執(zhí)行:
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)1、模擬range
class Range:
def __init__(self, n, stop, step):
self.n = n
self.stop = stop
self.step = step
def __next__(self):
if self.n >= self.stop:
raise StopIteration
x = self.n
self.n += self.step
return x
def __iter__(self):
return self
for i in Range(1, 7, 3):
print(i)
#1
#42、斐波那契數(shù)列
class Fib:
def __init__(self):
self._a = 0
self._b = 1
def __iter__(self):
return self
def __next__(self):
self._a, self._b = self._b, self._a + self._b
return self._a
f1 = Fib()
for i in f1:
if i > 100:
break
print('%s ' % i, end='')
# 1 1 2 3 5 8 13 21 34 55 89二、生成器
1、yield
在 Python 中,使用了 yield 的函數(shù)被稱為生成器(generator)。
跟普通函數(shù)不同的是,生成器是一個返回迭代器的函數(shù),只能用于迭代操作,更簡單點理解生成器就是一個迭代器。
在調(diào)用生成器運行的過程中,每次遇到 yield 時函數(shù)會暫停并保存當(dāng)前所有的運行信息,返回 yield 的值, 并在下一次執(zhí)行 next() 方法時從當(dāng)前位置繼續(xù)運行。
調(diào)用一個生成器函數(shù),返回的是一個迭代器對象。
yield后面可以加多個數(shù)值(可以是任意類型),但返回的值是元組類型的。
- 提供一種自定義迭代器的方式
- yield可以暫停住函數(shù),并提供當(dāng)前的返回值
import sys
def fibonacci(n): # 函數(shù) - 斐波那契
a, b, counter = 0, 1, 0
while True:
if counter > n:
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) #f 是一個生成器
print(type(f)) # 'generator'>
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()yield和return:
- 相同點:兩者都是在函數(shù)內(nèi)部使用,都可以返回值,并且返回值沒有類型和個數(shù)的限制
- 不同點:return只能返回一次值;yield可以返回多次值
2、自定義range()方法
def my_range(start, stop, step=1):
while start < stop:
yield start
start += 1
g = my_range(0, 3)
print(f"list(g): {list(g)}")復(fù)雜版本:
def range(*args, **kwargs):
if not kwargs:
if len(args) == 1:
count = 0
while count < args[0]:
yield count
count += 1
if len(args) == 2:
start, stop = args
while start < stop:
yield start
start += 1
if len(args) == 3:
start, stop, step = args
while start < stop:
yield start
start += step
else:
step = 1
if len(args) == 1:
start = args[0]
if len(args) == 2:
start, stop = args
for k, v in kwargs.items():
if k not in ['start', 'step', 'stop']:
raise ('參數(shù)名錯誤')
if k == 'start':
start = v
elif k == 'stop':
stop = v
elif k == 'step':
step = v
while start < stop:
yield start
start += step
for i in range(3):
print(i) # 0,1,2
for i in range(99, 101):
print(i) # 99,100
for i in range(1, 10, 3):
print(i) # 1,4,7
for i in range(1, step=2, stop=5):
print(i) # 1,3
for i in range(1, 10, step=2):
print(i) # 1,3,5,7,93、生成器表達式(i.for .in)
把列表推導(dǎo)式的[]換成()就是生成器表達式 。
優(yōu)點:比起列表推導(dǎo)式,可以省內(nèi)存,一次只產(chǎn)生一個值在內(nèi)存中
t = (i for i in range(10)) print(t) # <generator object at 0x00000000026907B0> print(next(t)) # 0 print(next(t)) # 1
舉例:
with open('32.txt', 'r', encoding='utf8') as f:
nums = [len(line) for line in f] # 列表推導(dǎo)式相當(dāng)于直接給你一筐蛋
print(max(nums)) # 2
with open('32.txt', 'r', encoding='utf8') as f:
nums = (len(line) for line in f) # 生成器表達式相當(dāng)于給你一只老母雞。
print(max(nums)) # ValueError: I/O operation on closed file.到此這篇關(guān)于Python迭代器與生成器的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python常見庫matplotlib學(xué)習(xí)筆記之畫圖文字的中文顯示
在Python中使用matplotlib或者plotnine模塊繪圖時,常常出現(xiàn)圖表中無法正常顯示中文的問題,下面這篇文章主要給大家介紹了關(guān)于Python常見庫matplotlib學(xué)習(xí)筆記之畫圖文字的中文顯示的相關(guān)資料,需要的朋友可以參考下2023-05-05
關(guān)于PyQt5中QtGui.QImage圖片顯示問題解析
PyQt作為Qt語言的Python擴展,可以用來方便快速的開發(fā)界面應(yīng)用,本文重點給大家介紹PyQt5中的QtGui.QImage圖片顯示問題分析,需要的朋友可以參考下2022-03-03
Python摳圖教程之使用OpenCV實現(xiàn)背景去除
這篇文章主要給大家介紹了關(guān)于Python摳圖教程之使用OpenCV實現(xiàn)背景去除的相關(guān)資料,背景去除是在很多視覺應(yīng)用里的主要預(yù)處理步驟,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2023-10-10
Python讀取含url圖片鏈接的txt文檔方法小結(jié)
這篇文章主要為大家詳細介紹了三種Python讀取含url圖片鏈接的txt文檔方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
Python3讀寫Excel文件(使用xlrd,xlsxwriter,openpyxl3種方式讀寫實例與優(yōu)劣)
這篇文章主要介紹了Python3讀寫Excel文件,使用xlrd,xlsxwriter,openpyxl3種方式讀寫實例與優(yōu)劣,需要的朋友可以參考下2020-02-02
基于Python實現(xiàn)PDF區(qū)域文本提取工具
這篇文章主要為大家介紹了如何通過Python實現(xiàn)一個非常精簡的圖像化的PDF區(qū)域選擇提取工具,文中示例代碼講解詳細,感興趣的小伙伴可以學(xué)習(xí)一下2021-12-12
Python如何利用xlrd和xlwt模塊操作Excel表格
這篇文章主要給大家介紹了關(guān)于Python如何利用xlrd和xlwt模塊操作Excel表格的相關(guān)資料,其中xlrd模塊實現(xiàn)對excel文件內(nèi)容讀取,xlwt模塊實現(xiàn)對excel文件的寫入,需要的朋友可以參考下2022-03-03

