Python程式設計如何在遞迴函式中使用迭代器

2022-09-25 02:03:08 字數 3476 閱讀 4352

首先,想要實現的功能是遞迴遍歷資料夾,遇到滿足條件的檔案時,用yield返回該檔案的位置。

如果不用遞迴器,可以這樣實現:

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)

即,深度優先遍歷,滿足要求時,將item_path補充到列表裡,之後返回上一層。

這裡有乙個問題,需要有乙個列表,把所有滿足條件的位址全存起來,佔記憶體。

使用迭代器可以用乙個,遍歷出來乙個,省記憶體

替換為迭代器,最先想到的是,把 return 換成 yield,使用for迴圈呼叫迭代器函式

def get_one_cage(root: str, cook_folder_name: str):

for i 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)

但是這樣的程式跑到內嵌函式時,進不去,我百思不得其解

現在看,應該是因為迭代器函式不是乙個函式,不是乙個命令語句,它只是乙個物件。

簡單說就是,python程式一般遵循:動詞+名詞的結構,或者動詞,比如:

a = 1

這句話實際上是把1賦值給了a,是有動詞的。

迭代器只是乙個名詞,必須用for語句呼叫或者next()方法呼叫才會執行,或者是print,yield,return等等,反正得加個動詞,不能孤零零乙個名詞。

而且上述**還有乙個漏洞。在第一段**中,我們用乙個全域性變數存放遍歷結果。在第二段**裡,我們本意是把結果yield到for迴圈呼叫的地方,但事實是,程式已經套了好幾層了,每次yiled只能返回一層。如下圖所示:

綜上兩點作出如下修改:

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)

程式執行結果如下:

顯然是返回了乙個迭代器,不是乙個str,其邏輯如下圖所示:

就好比,本意是:

小明把沙袋傳給小紅,小紅傳給小蘭

但現在是:

小明把沙袋傳給了小紅,小紅被傳了出去

修改如下:

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))

邏輯如下:

還有一種情況是學長原始碼裡的:使用for呼叫迭代器:

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

這使用於多個檔案的返回,原始碼裡還配合isfile使用,這裡是簡化版,所以顯得冗餘。

兩種方式均可以正常使用。

昨天這篇文章寫完後,遇到了bug,簡單說就是,如果乙個資料夾系統沒有我們想要的檔案,遞迴到最深一層資料夾時,會報錯

1可以理解為:老闆讓員工找一樣東西,員工外包給編外人員。如果編外人員找到了想要的東西,一路傳遞回去,可以正常交差。如果沒找到,編外人員就會一直找,不停歇,找遍了所有能找到的地方(遍歷完整個資料夾)也沒能找到,就會報錯stopiteration。

因此,問題核心是,沒有乙個返回機制。修改辦法是在遍歷最後加乙個空返回

def get_one_cage(root: str):

for index, item in enumerate(os.listdir(root)):

jxjetq 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語句處理異常:

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

會有如上報錯,正常。

最後的yield換成return也是可以的,但最好還是用yield,兩個混起來用怪怪的。

個人推薦第二種方法

注:copy()可以不用要

python如何裝飾遞迴函式

裝飾函式printtime 列印遞迴函式執行時間 def printtime func wraps func def args,kwargs start time print func args,kwargs end time print spent time s end start 遞迴函式n d...

如何在python中引用c c 函式

由於python效能問題的原因,在實際專案中往往會在python中去呼叫c的一些方法,本文將介紹在centos8下面python去呼叫c的方法。c的示例 如下 include include include include typedef struct node intadd node node v...

如何在Linux使用python3程式設計

wgettar zxvf python 3.9.1.tgz解壓之後進入解壓後的檔案,然後檢視 cd python 3.9.1沒有gcc是不能編譯的,如果沒有的話,先安裝乙個 yum install y gcc如果沒有的話,會報以下錯誤 接著按順序輸入以下 configure 配置檔案 make 編譯...