递归将项目添加到列表中 [英] Add an item into a list recursively
问题描述
嗨.我想知道是否有一种方法可以将项目递归添加到列表中.该功能应该打印与fname匹配的文件的路径名.因此,fname是文件名,路径是文件所在的文件夹.如果路径文件夹中有文件夹,它将进入内部并查找fname文件.到目前为止,我已经能够找到所有文件.但是我不能递归地添加列表.
Hi. I was wondering if there is a way to add items into a list recursively. The function is supposed to print the path names of the file that matches with fname. So fname is the name of the file and the path is the folder in which the file is located. If there are folders inside the path folder it will go inside and look for the fname file. so far I am able to find all the files. But I am not able to append the list recursively.
def findAll(fname, path):
lst= []
for item in os.listdir(path):
n = os.path.join(path, item)
try:
if item == fname:
lst.append(n)
except:
findAll(fname,n)
return lst
推荐答案
通常,我不会给出完整的解决方案,因为这听起来像是作业(这也是为什么我避免使用os.walk
的原因),但是由于您有发布您的尝试,这是一种解释和解决方案:
Normally, I wouldn't give a full solution because this smells like homework (which is also why I'm avoiding os.walk
), but since you have posted your attempt, here's an explanation and a solution:
一方面,每次调用findAll
时,都要初始化lst
.当然,您在最后返回了它,但是您对返回值不做任何事情,因此效果lst.append
包含在递归中,因此在外部不可见.让我尝试绘制图表来解释这一点(使用一级递归):
For one thing, every time you call findAll
, you initialize lst
. Sure, you return it at the end, but you don't do anything with the return value, so the effect lst.append
is contained within the recursion and is therefore not visible outside. Let me try to draw diagram to explain this (with one level of recursion):
+--------------------------------------------------+
|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 |
+--------------------------------------------------+
有两种方法可以解决此问题:
There are a couple of ways by which you can fix this:
- 将
lst
移至findAll
之外的范围(个人,这是我会做的事) - 使用递归调用的返回值修改
lst
- move
lst
to a scope outsidefindAll
(personally, this is what I would do) - use the return value from the recursive call to modify
lst
将lst
移至findAll
move lst
to a scope outside 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
将包含您想要的值
After findAll
has terminated, lst
will contain the values you want
使用递归调用的返回值修改lst
use the return value from the recursive call to modify 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
:
PS: of course, the non-homework way to do this would be to use 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要求使用不使用全局变量的版本:
EDIT: OP asked for a version that doesn't use global variables:
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
这篇关于递归将项目添加到列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!