【问题标题】:Recursion base case fails递归基本案例失败
【发布时间】:2015-02-08 03:46:32
【问题描述】:

我正在寻找代码最后一行中的错误,但我不知道它是什么。有任何想法吗?

def letterScore( let ):
    let.lower()
    if let in 'aAnNoOeErRsStTuUiIlL':
        return 1
    elif let in 'dDgG':
        return 2
    elif let in 'bBcCpPmM':
        return 3
    elif let in 'fFhHvVwWyY':
        return 4
    elif let in 'kK':
        return 5 
    elif let in 'jJxX':
        return 8
    elif let in 'qQzZ':
        return 10
    else:
        return 0

def scrabbleScore( s ):
    return letterScore(s[0]) + scrabbleScore(s[1:len(s)])

【问题讨论】:

  • 正如 alfasin 提到的,let.lower() 不会改变 let:它不能因为 Python 字符串是不可变的。但是,如果您执行let = let.lower(),则会创建一个新字符串,并且该新字符串将绑定到名称let

标签: python debugging recursion computer-science


【解决方案1】:

问:你的递归函数什么时候“触底”并停止递归?

答:没有。

问:应该什么时候停止递归?

答:当len(s) == 0.

问。当len(s) == 0实际上会发生什么?

A.你打电话给s[0],它就死了IndexError

如果你希望它是递归的,它应该看起来像

def scrabble_score(s):
    if s:   # Pythonic idiom for `len(s) > 0`
        return letter_score(s[0]) + scrabble_score(s[1:])
    else:
        return 0

然而没有充分的理由让它递归;迭代方法更简单、更快,

SCORES = dict(zip(
    "abcdefghijklmnopqrstuvwxyz",
    [1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10]
))

def letter_score(ch, scores=SCORES):
    return scores.get(ch.lower(), 0)

def scrabble_score(word):
    return sum(letter_score(ch) for ch in word)

【讨论】:

    【解决方案2】:

    问题出在递归调用中:

    scrabbleScore(s[0])
    

    s 作为空字符串(递归的基本情况)返回时,此调用将失败并引发异常。

    附注:这行没有意义:let.lower() - 它什么也没做。

    【讨论】:

    • 没错,当s 为空时scrabbleScore(s[1:len(s)]) 将失败,但s[1:len(s)] 实际上没问题:引发IndexError 的是letterScore(s[0]) 中的s[0]。您可以对空字符串进行切片,但不能对其编制索引。例如''[0:1],''[1:1] 甚至''[1:0] 都会产生一个空字符串。
    • @PM2Ring 你是对的 - 我更正了答案,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 2022-01-19
    • 2017-07-11
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多