python - 用于查找值索引的递归和返回

标签 python python-3.x recursion

因此,我在一张 CSE 101 幻灯片中遇到了一个练习题,该问题要求使用递归在列表或字符串中查找值。如果该值位于列表或字符串内,则返回与该值匹配的第一个索引位置。我能够解决它,但我不明白它为什么有效。这是我的代码:

def rindex(a, pos):
    if pos not in a:
        return None
    elif pos in a:
        if a[0] != pos:
            return rindex(a[1:], pos) + 1
    return 0

具体来说,我不明白为什么

return 0

使我的功能正常工作。为什么它返回正确的值而不是 0?

最佳答案

每次在函数中遇到 return 时,都会返回结果并停止函数执行。这意味着,如果 pos 存在于当前 a 切片中,则永远不会遇到 return 0,除非当前切片的第一个元素等于 pos - 此时您返回 0 以指示索引不应增加。如果您不返回它,则默认情况下,rindex() 将返回 None,当您尝试将其与 + 1 求和时,会导致错误递归链。

话虽这么说,每当你执行 if pos not in a: 时,你都会迭代列表 a 来搜索 pos 所以您的代码将非常低效(特别是因为您随后在 elif block 中再次执行完全相同的搜索,而简单的 else 就足够了)。您可以将代码重新编写为:

def rindex(a, pos):
    if a[0] == pos:  # element found, do not increase the index
        return 0
    return rindex(a[1:], pos) + 1

因此,每次递归时您只进行切片而不是两次迭代。这里最大的问题是,如果在列表递归到达末尾时未找到 pos,它将引发 IndexError。如果您更喜欢返回值而不是异常,您可以捕获它并返回任何类型的值,因此在您的情况下:

def rindex(a, pos):
    if a[0] == pos:  # element found, do not increase the index
        return 0
    try:
        return rindex(a[1:], pos) + 1
    except (IndexError, TypeError):  # capture both to propagate
        return None

但是,请记住,即使执行列表切片也不是最有效的解决方案,尤其是在考虑内存时。由于 Python 将名称传递给引用,因此您可以递归整个列表,而几乎没有任何损失,并使用索引递归地遍历列表,即:

def rindex(a, pos, loc=0):
    if a[loc] == pos:
        return loc
    return rindex(a, pos, loc+1)

您甚至不必执行递归try .. except编排来捕获错误 - 您可以直接在函数中执行抢占式( LBYL 样式):

def rindex(a, pos, loc=0):
    if len(a) >= loc:
        return None
    if a[loc] == pos:
        return loc
    return rindex(a, pos, loc + 1)

或者事后(EAFP风格):

def rindex(a, pos, loc=0):
    try:
        if a[loc] == pos:
            return loc
    except IndexError:
        return None
    return rindex(a, pos, loc + 1)

当未找到元素时,这些还允许您传递任意索引(即 -1),因为验证与实际索引搜索分开,因此不会影响索引总和。

关于python - 用于查找值索引的递归和返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51495560/

相关文章:

python - 虚拟环境中的 Opencv3 和 Python 2.7 - AttributeError : 'module' object has no attribute 'createLBPHFaceRecognizer'

python - 将所有数值替换为格式化字符串

python - 目标变量的字符串和数字的混合

python - [Python][cx-freeze] 导入错误 : cannot import name 'ExcelFormulaParser'

parsing - 'not' 的 lisp 解析

python - 动态绘制 n 个图

python - Matplotlib 分离 3D 数据的 2D 轮廓投影图

python - 从Python中的名称列中删除前缀

search - 如何(递归)搜索 Windows 7 中的所有文件内容?

javascript - 如何使这个同步递归函数异步