递归函数在Python中没有返回[重复]

时间:2021-10-29 01:42:52

This question already has an answer here:

这个问题在这里已有答案:

I have this piece of code, for some reason when I try to return the path, I get None instead:

我有这段代码,出于某种原因,当我尝试返回路径时,我得到的是None:

def get_path(dictionary, rqfile, prefix=[]):

for filename in dictionary.keys():
    path = prefix+[filename]
    if not isinstance(dictionary[filename], dict):

        if rqfile in str(os.path.join(*path)):
            return str(os.path.join(*path))

    else:
        get_path(directory[filename], rqfile, path)

Is there a way to solve this? Thanks in advance.

有办法解决这个问题吗?提前致谢。

2 个解决方案

#1


15  

You need to return the recursive result:

您需要返回递归结果:

else:
   return get_path(directory[filename], rqfile, path)

otherwise the function simply ends after executing that statement, resulting in None being returned.

否则函数只在执行该语句后结束,导致返回None。

You probably want to drop the else: and always return at the end:

您可能想要删除else:并始终返回结束:

for filename in dictionary.keys():
    path = prefix+[filename]
    if not isinstance(dictionary[filename], dict):

        if rqfile in str(os.path.join(*path)):
            return str(os.path.join(*path))

    return get_path(directory[filename], rqfile, path)

because if rqfile in str(os.path.join(*path)) is False then you end your function without a return as well. If recursing in that case is not the right option, but returning None is not, you need to handle that edgecase too.

因为如果str(os.path.join(* path))中的rqfile为False,那么你也可以在没有返回的情况下结束你的函数。如果在这种情况下递归不是正确的选项,但是返回None则不是,则还需要处理该edgecase。

#2


0  

While I think Martijn Pieters answer addresses the primary issue in his answer (you need to return from the recursive case), I don't think his suggested code will work right.

虽然我认为Martijn Pieters在他的回答中解决了主要问题(你需要从递归案例中返回),但我不认为他建议的代码能够正常工作。

You're trying to implement a depth-first search for the rqfile value in the nested dictionary dict. But your current code doesn't handle the recursive case correctly. It needs to respond appropriately if the result is found in one of its recursive calls, or if the recursive call failed to find the target.

您正尝试在嵌套字典dict中实现深度优先搜索rqfile值。但是您当前的代码无法正确处理递归情况。如果在其中一个递归调用中找到结果,或者如果递归调用未能找到目标,则需要做出相应的响应。

Here's what I think you need, with some things renamed or rearranged for clarity:

这是我认为你需要的东西,为了清楚起见,重命名或重新排列了一些东西:

def get_path(directory, rqfile, prefix=[]):
    for filename, value in directory.items():
        path_list = prefix + [filename]
        if not isinstance(value, dict): # base case
            path = os.path.join(*path_list)
            if rqfile in path:   # Found the file. Do you want to do something
                return path      # with the value here, or is it junk?

        else: # recursive case
            try:
                return get_path(value, rqfile, path_list) # this only returns if 
            except ValueError:                     # the recursion doesn't raise
                pass

    raise ValueError("Requested file not found") # not found here or in children

Example usage:

>>> directory = {"a": "a info",
                 "b": {"c": "b/c info", "d": "b/d info"},
                 "e": {"f": "e/f info", "g": {"h": "e/g/h info"}}}
>>> print(get_path(directory, "h"))
e\g\h
>>> print(get_path(directory, r'g\h'))
e\g\h

If you don't want to raise exceptions when the file is not found, you could also return a sentinel value like None in place of the last line, and check for the sentinel value it in the recursive case instead of the try/except:

如果你不想在找不到文件时引发异常,你也可以返回一个像None这样的标记值代替最后一行,并在递归情况下检查它的sentinel值而不是try / except:

 result = get_path(value, rqfile, path)
 if result is not None:
     return result

#1


15  

You need to return the recursive result:

您需要返回递归结果:

else:
   return get_path(directory[filename], rqfile, path)

otherwise the function simply ends after executing that statement, resulting in None being returned.

否则函数只在执行该语句后结束,导致返回None。

You probably want to drop the else: and always return at the end:

您可能想要删除else:并始终返回结束:

for filename in dictionary.keys():
    path = prefix+[filename]
    if not isinstance(dictionary[filename], dict):

        if rqfile in str(os.path.join(*path)):
            return str(os.path.join(*path))

    return get_path(directory[filename], rqfile, path)

because if rqfile in str(os.path.join(*path)) is False then you end your function without a return as well. If recursing in that case is not the right option, but returning None is not, you need to handle that edgecase too.

因为如果str(os.path.join(* path))中的rqfile为False,那么你也可以在没有返回的情况下结束你的函数。如果在这种情况下递归不是正确的选项,但是返回None则不是,则还需要处理该edgecase。

#2


0  

While I think Martijn Pieters answer addresses the primary issue in his answer (you need to return from the recursive case), I don't think his suggested code will work right.

虽然我认为Martijn Pieters在他的回答中解决了主要问题(你需要从递归案例中返回),但我不认为他建议的代码能够正常工作。

You're trying to implement a depth-first search for the rqfile value in the nested dictionary dict. But your current code doesn't handle the recursive case correctly. It needs to respond appropriately if the result is found in one of its recursive calls, or if the recursive call failed to find the target.

您正尝试在嵌套字典dict中实现深度优先搜索rqfile值。但是您当前的代码无法正确处理递归情况。如果在其中一个递归调用中找到结果,或者如果递归调用未能找到目标,则需要做出相应的响应。

Here's what I think you need, with some things renamed or rearranged for clarity:

这是我认为你需要的东西,为了清楚起见,重命名或重新排列了一些东西:

def get_path(directory, rqfile, prefix=[]):
    for filename, value in directory.items():
        path_list = prefix + [filename]
        if not isinstance(value, dict): # base case
            path = os.path.join(*path_list)
            if rqfile in path:   # Found the file. Do you want to do something
                return path      # with the value here, or is it junk?

        else: # recursive case
            try:
                return get_path(value, rqfile, path_list) # this only returns if 
            except ValueError:                     # the recursion doesn't raise
                pass

    raise ValueError("Requested file not found") # not found here or in children

Example usage:

>>> directory = {"a": "a info",
                 "b": {"c": "b/c info", "d": "b/d info"},
                 "e": {"f": "e/f info", "g": {"h": "e/g/h info"}}}
>>> print(get_path(directory, "h"))
e\g\h
>>> print(get_path(directory, r'g\h'))
e\g\h

If you don't want to raise exceptions when the file is not found, you could also return a sentinel value like None in place of the last line, and check for the sentinel value it in the recursive case instead of the try/except:

如果你不想在找不到文件时引发异常,你也可以返回一个像None这样的标记值代替最后一行,并在递归情况下检查它的sentinel值而不是try / except:

 result = get_path(value, rqfile, path)
 if result is not None:
     return result