Python中迭代器與生成器的用法
一、迭代器(foreach)
1、可迭代的對(duì)象
內(nèi)置有__iter__方法的都叫可迭代的對(duì)象。
Python內(nèi)置str、list、tuple、dict、set、file都是可迭代對(duì)象。
x = 1.__iter__ # SyntaxError: invalid syntax # 以下都是可迭代的對(duì)象 name = 'nick'.__iter__ print(type(name)) # 'method-wrapper'>
2、迭代器對(duì)象
執(zhí)行可迭代對(duì)象的__iter__方法,拿到的返回值就是迭代器對(duì)象。
只有字符串和列表都是依賴(lài)索引取值的,而其他的可迭代對(duì)象都是無(wú)法依賴(lài)索引取值的,只能使用迭代器對(duì)象。
- 內(nèi)置有
__iter__方法,執(zhí)行該方法會(huì)拿到迭代器本身。 - 內(nèi)置
__next__方法,執(zhí)行該方法會(huì)拿到迭代器對(duì)象中的一個(gè)值。
s = 'hello'
iter_s = s.__iter__()
print(type(iter_s)) # 'str_iterator'> iter_s為迭代器對(duì)象
while True:
try:
print(iter_s.__next__())
except StopIteration:
break
#hello3、迭代器有兩個(gè)基本的方法:iter() 和 next()。
s = 'hello'
iter_s = iter(s) # 創(chuàng)建迭代器對(duì)象
print(type(iter_s)) # iter_s為迭代器對(duì)象
while True:
try:
print(next(iter_s)) # 輸出迭代器的下一個(gè)元素
except StopIteration:
break
# hello4、for迭代器循環(huán)
可迭代對(duì)象可以直接使用常規(guī)for語(yǔ)句進(jìn)行遍歷
for循環(huán)稱(chēng)為迭代器循環(huán),in后必須是可迭代的對(duì)象。
#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、實(shí)現(xiàn)迭代器(__next__和__iter__)
把一個(gè)類(lèi)作為一個(gè)迭代器使用需要在類(lèi)中實(shí)現(xiàn)兩個(gè)方法 __iter__() 與 __next__() 。
- __iter__() 方法返回一個(gè)特殊的迭代器對(duì)象, 這個(gè)迭代器對(duì)象實(shí)現(xiàn)了 __next__() 方法并通過(guò) StopIteration 異常標(biāo)識(shí)迭代的完成。
- __next__() 方法會(huì)返回下一個(gè)迭代器對(duì)象。
- StopIteration 異常用于標(biāo)識(shí)迭代的完成,防止出現(xiàn)無(wú)限循環(huán)的情況,在 __next__() 方法中我們可以設(shè)置在完成指定循環(huán)次數(shù)后觸發(fā) StopIteration 異常來(lái)結(jié)束迭代。
創(chuàng)建一個(gè)返回?cái)?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ù)被稱(chēng)為生成器(generator)。
跟普通函數(shù)不同的是,生成器是一個(gè)返回迭代器的函數(shù),只能用于迭代操作,更簡(jiǎn)單點(diǎn)理解生成器就是一個(gè)迭代器。
在調(diào)用生成器運(yùn)行的過(guò)程中,每次遇到 yield 時(shí)函數(shù)會(huì)暫停并保存當(dāng)前所有的運(yùn)行信息,返回 yield 的值, 并在下一次執(zhí)行 next() 方法時(shí)從當(dāng)前位置繼續(xù)運(yùn)行。
調(diào)用一個(gè)生成器函數(shù),返回的是一個(gè)迭代器對(duì)象。
yield后面可以加多個(gè)數(shù)值(可以是任意類(lèi)型),但返回的值是元組類(lèi)型的。
- 提供一種自定義迭代器的方式
- 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 是一個(gè)生成器
print(type(f)) # 'generator'>
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()yield和return:
- 相同點(diǎn):兩者都是在函數(shù)內(nèi)部使用,都可以返回值,并且返回值沒(méi)有類(lèi)型和個(gè)數(shù)的限制
- 不同點(diǎn):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ù)名錯(cuò)誤')
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、生成器表達(dá)式(i.for .in)
把列表推導(dǎo)式的[]換成()就是生成器表達(dá)式 。
優(yōu)點(diǎn):比起列表推導(dǎo)式,可以省內(nèi)存,一次只產(chǎn)生一個(gè)值在內(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á)式相當(dāng)于給你一只老母雞。
print(max(nums)) # ValueError: I/O operation on closed file.到此這篇關(guān)于Python迭代器與生成器的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python常見(jiàn)庫(kù)matplotlib學(xué)習(xí)筆記之畫(huà)圖文字的中文顯示
在Python中使用matplotlib或者plotnine模塊繪圖時(shí),常常出現(xiàn)圖表中無(wú)法正常顯示中文的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Python常見(jiàn)庫(kù)matplotlib學(xué)習(xí)筆記之畫(huà)圖文字的中文顯示的相關(guān)資料,需要的朋友可以參考下2023-05-05
關(guān)于PyQt5中QtGui.QImage圖片顯示問(wèn)題解析
PyQt作為Qt語(yǔ)言的Python擴(kuò)展,可以用來(lái)方便快速的開(kāi)發(fā)界面應(yīng)用,本文重點(diǎn)給大家介紹PyQt5中的QtGui.QImage圖片顯示問(wèn)題分析,需要的朋友可以參考下2022-03-03
Python摳圖教程之使用OpenCV實(shí)現(xiàn)背景去除
這篇文章主要給大家介紹了關(guān)于Python摳圖教程之使用OpenCV實(shí)現(xiàn)背景去除的相關(guān)資料,背景去除是在很多視覺(jué)應(yīng)用里的主要預(yù)處理步驟,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
Python讀取含url圖片鏈接的txt文檔方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了三種Python讀取含url圖片鏈接的txt文檔方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
python打開(kāi)文件并獲取文件相關(guān)屬性的方法
這篇文章主要介紹了python打開(kāi)文件并獲取文件相關(guān)屬性的方法,涉及Python操作文件的相關(guān)技巧,需要的朋友可以參考下2015-04-04
python UNIX_TIMESTAMP時(shí)間處理方法分析
這篇文章主要介紹了python UNIX_TIMESTAMP時(shí)間處理方法,結(jié)合實(shí)例形式分析了Python針對(duì)UNIX_TIMESTAMP時(shí)間的常見(jiàn)運(yùn)算技巧,需要的朋友可以參考下2016-04-04
Python3讀寫(xiě)Excel文件(使用xlrd,xlsxwriter,openpyxl3種方式讀寫(xiě)實(shí)例與優(yōu)劣)
這篇文章主要介紹了Python3讀寫(xiě)Excel文件,使用xlrd,xlsxwriter,openpyxl3種方式讀寫(xiě)實(shí)例與優(yōu)劣,需要的朋友可以參考下2020-02-02
基于Python實(shí)現(xiàn)PDF區(qū)域文本提取工具
這篇文章主要為大家介紹了如何通過(guò)Python實(shí)現(xiàn)一個(gè)非常精簡(jiǎn)的圖像化的PDF區(qū)域選擇提取工具,文中示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下2021-12-12
Python如何利用xlrd和xlwt模塊操作Excel表格
這篇文章主要給大家介紹了關(guān)于Python如何利用xlrd和xlwt模塊操作Excel表格的相關(guān)資料,其中xlrd模塊實(shí)現(xiàn)對(duì)excel文件內(nèi)容讀取,xlwt模塊實(shí)現(xiàn)對(duì)excel文件的寫(xiě)入,需要的朋友可以參考下2022-03-03

