Python編程如何在遞歸函數(shù)中使用迭代器
首先,想要實(shí)現(xiàn)的功能是遞歸遍歷文件夾,遇到滿足條件的文件時(shí),用yield返回該文件的位置。
如果不用遞歸器,可以這樣實(shí)現(xiàn):
path_list = []
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
path_list.append(item_path)
return
elif os.path.isdir(item_path):
get_one_cage(item_path, cook_folder_name)
即,深度優(yōu)先遍歷,滿足要求時(shí),將item_path補(bǔ)充到列表里,之后返回上一層。
這里有一個(gè)問(wèn)題,需要有一個(gè)列表,把所有滿足條件的地址全存起來(lái),占內(nèi)存。
使用迭代器可以用一個(gè),遍歷出來(lái)一個(gè),省內(nèi)存
替換為迭代器,最先想到的是,把 return 換成 yield,使用for循環(huán)調(diào)用迭代器函數(shù)
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
get_one_cage(item_path, cook_folder_name)
但是這樣的程序跑到內(nèi)嵌函數(shù)時(shí),進(jìn)不去,我百思不得其解
現(xiàn)在看,應(yīng)該是因?yàn)榈骱瘮?shù)不是一個(gè)函數(shù),不是一個(gè)命令語(yǔ)句,它只是一個(gè)對(duì)象。
簡(jiǎn)單說(shuō)就是,python程序一般遵循:動(dòng)詞+名詞的結(jié)構(gòu),或者動(dòng)詞,比如:
a = 1
這句話實(shí)際上是把1賦值給了a,是有動(dòng)詞的。
迭代器只是一個(gè)名詞,必須用for語(yǔ)句調(diào)用或者next()方法調(diào)用才會(huì)執(zhí)行,或者是print,yield,return等等,反正得加個(gè)動(dòng)詞,不能孤零零一個(gè)名詞。
而且上述代碼還有一個(gè)漏洞。在第一段代碼中,我們用一個(gè)全局變量存放遍歷結(jié)果。在第二段代碼里,我們本意是把結(jié)果yield到for循環(huán)調(diào)用的地方,但事實(shí)是,程序已經(jīng)套了好幾層了,每次yiled只能返回一層。如下圖所示:

綜上兩點(diǎn)作出如下修改:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
yield get_one_cage(item_path, cook_folder_name)
程序執(zhí)行結(jié)果如下:

顯然是返回了一個(gè)迭代器,不是一個(gè)str,其邏輯如下圖所示:

就好比,本意是:
小明把沙袋傳給小紅,小紅傳給小蘭
但現(xiàn)在是:
小明把沙袋傳給了小紅,小紅被傳了出去
修改如下:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path, cook_folder_name))
邏輯如下:

還有一種情況是學(xué)長(zhǎng)源碼里的:使用for調(diào)用迭代器:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
for i in get_one_cage(item_path, cook_folder_name):
yield i
這使用于多個(gè)文件的返回,源碼里還配合isfile使用,這里是簡(jiǎn)化版,所以顯得冗余。
兩種方式均可以正常使用。
昨天這篇文章寫完后,遇到了bug,簡(jiǎn)單說(shuō)就是,如果一個(gè)文件夾系統(tǒng)沒有我們想要的文件,遞歸到最深一層文件夾時(shí),會(huì)報(bào)錯(cuò)

1
可以理解為:老板讓員工找一樣?xùn)|西,員工外包給編外人員。如果編外人員找到了想要的東西,一路傳遞回去,可以正常交差。如果沒找到,編外人員就會(huì)一直找,不停歇,找遍了所有能找到的地方(遍歷完整個(gè)文件夾)也沒能找到,就會(huì)報(bào)錯(cuò)StopIteration。
因此,問(wèn)題核心是,沒有一個(gè)返回機(jī)制。修改辦法是在遍歷最后加一個(gè)空返回
def get_one_cage(root: str):
for index, item in enumerate(os.listdir(root)):
item_path = os.path.join(root, item)
if item == 'cooked_xyz':
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path))
elif index == len(os.listdir(root).copy()) - 1:
yield
或者是利用try… except語(yǔ)句處理異常:
def get_one_cage(root: str):
try:
for item in os.listdir(root):
item_path = os.path.join(root, item)
if item == 'cooked_xyz':
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path))
except:
yield

會(huì)有如上報(bào)錯(cuò),正常。
最后的yield換成return也是可以的,但最好還是用yield,兩個(gè)混起來(lái)用怪怪的。
個(gè)人推薦第二種方法
注:copy()可以不用要
以上就是Python編程如何在遞歸中使用迭代器的詳細(xì)內(nèi)容,更多關(guān)于Python編程遞歸中使用迭代器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
以上就是Python編程如何在遞歸函數(shù)中使用迭代器的詳細(xì)內(nèi)容,更多關(guān)于Python遞歸函數(shù)中使用迭代器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python使用matplotlib實(shí)現(xiàn)繪制自定義圖形功能示例
這篇文章主要介紹了Python使用matplotlib實(shí)現(xiàn)繪制自定義圖形功能,結(jié)合實(shí)例形式分析了Python基于matplotlib模塊實(shí)現(xiàn)自定義圖形繪制相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
基于Python+Pygame實(shí)現(xiàn)變異狗大戰(zhàn)游戲
只有你想不到,沒有我找不到寫不了的好游戲!這篇文章就來(lái)和大家分享一下如何基于Python+Pygame實(shí)現(xiàn)變異狗大戰(zhàn)游戲,感興趣的可以了解一下2023-03-03
從列表或字典創(chuàng)建Pandas的DataFrame對(duì)象的方法
這篇文章主要介紹了從列表或字典創(chuàng)建Pandas的DataFrame對(duì)象的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
python實(shí)現(xiàn)的登陸Discuz!論壇通用代碼分享
這篇文章主要介紹了python實(shí)現(xiàn)的登陸Discuz!論壇通用代碼分享,需要的朋友可以參考下2014-07-07
Python人工智能深度學(xué)習(xí)RNN模型結(jié)構(gòu)流程
這篇文章主要為大家介紹了Python人工智能深度學(xué)習(xí)RNN的模型流程結(jié)構(gòu),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11
Matplotlib繪制混淆矩陣的實(shí)現(xiàn)
對(duì)于機(jī)器學(xué)習(xí)多分類模型來(lái)說(shuō),其評(píng)價(jià)指標(biāo)除了精度之外,常用的還有混淆矩陣和分類報(bào)告,下面來(lái)展示一下如何繪制混淆矩陣,這在論文中經(jīng)常會(huì)用到。感興趣的可以了解一下2021-05-05
Flask登錄注冊(cè)項(xiàng)目的簡(jiǎn)單實(shí)現(xiàn)
一個(gè)簡(jiǎn)單的用戶注冊(cè)和登錄的頁(yè)面,涉及到驗(yàn)證,數(shù)據(jù)庫(kù)存儲(chǔ)等等,本文主要介紹了Flask登錄注冊(cè)項(xiàng)目的簡(jiǎn)單實(shí)現(xiàn),從目錄結(jié)構(gòu)開始,感興趣的可以了解一下2021-05-05
python 實(shí)現(xiàn)在txt指定行追加文本的方法
下面小編就為大家分享一篇python 實(shí)現(xiàn)在txt指定行追加文本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04

