通常,我不会给出完整的解决方案,因为这闻起来像家庭作业(这也是我避免使用os.walk 的原因),但既然你已经发布了你的尝试,这里有一个解释和一个解决方案:
一方面,每次调用findAll,都会初始化lst。当然,你在最后返回它,但你不对返回值做任何事情,所以效果lst.append 包含在递归中,因此在外面不可见。让我尝试绘制图表来解释这一点(使用一级递归):
+--------------------------------------------------+
|Outer Level: |
| |
|`lst = []` |
|found file f1 with name fname |
|`lst.append(f1)` |
|+------------------------------------------------+|
||Inner Level ||
|| ||
||`lst=[]` ||
||found file f2 with name fname ||
||`lst.append(f2)` ||
||`return lst` ||
|+------------------------------------------------+|
|a list is returned from recursive call, |
|but not assigned to a variable. |
|Therefore, `lst` remains unchanged |
+--------------------------------------------------+
有几种方法可以解决这个问题:
- 将
lst 移动到findAll 之外的范围内(我个人会这样做)
- 使用递归调用的返回值修改
lst
将lst移动到findAll之外的范围
lst= []
def findAll(fname, path):
global lst
for item in os.listdir(path):
n = os.path.join(path, item)
try: # really though, you don't need to use try/except here
if item == fname:
lst.append(n)
else:
findAll(fname,n)
except:
pass
findAll 终止后,lst 将包含您想要的值
使用递归调用的返回值修改lst
def findAll(fname, path, answer=None):
if answer == None:
answer = []
for item in os.listdir(path):
n = os.path.join(path, item)
try:
if item == fname:
answer += [n]
except:
findAll(fname,n, answer)
return answer
希望对你有帮助
PS:当然,不做作业的方法是使用os.walk:
answer = []
def findAll(fname, dirpath):
dirpath, dirnames, filenames = os.walk(dirpath)
for filename in filenames:
if filename == fname:
answer.append(os.path.join(dirpath, filename))
for dirname in dirnames:
findAll(fname, os.path.join(dirpath, dirname))
# now, answer contains all the required filepaths
编辑:OP 要求提供不使用全局变量的版本:
def findAll(fname, root, answer=None):
if answer == None:
answer = []
for entry in os.listdir(root):
if os.path.isdir(os.path.join(root, entry)):
answer += findAll(fname, os.path.join(root, entry))
else:
if entry == fname:
answer.append(os.path.join(root, entry))
return answer