理解递归和多个返回

时间:2014-05-31 18:58:23

标签: python recursion

我正在通过麻省理工学院6.00课程在OpenCourseWare上学习,我在递归讲座上遇到了一些麻烦。我想我理解的基本思想是,你可以把一些问题分解成更小,可重复的问题。我遇到麻烦的地方是了解它在实际代码中是如何工作的。有一个我不太明白的具体例子......

def toChars(s):
    import string
    s = string.lower(s)
    ans = ''
    for c in s:
        if c in string.lowercase:
            ans = ans + c
    return ans

def isPal(s):
    if len(s) <= 1:
        return True
    else:
        return s[0] == s[-1] and isPal(s[1:-1])

def isPalindrome(s):
    """Returns True if s is a palindrome and False otherwise"""
    return isPal(toChars(s))

此代码应检查字符串是否是回文。我对isPal的运作方式有点失落。这是我正在读它们的步骤......

  1. 检查s是否为一个字符或更少,如果返回True。
  2. 如果s有多个字符,则从比较第一个和最后一个字符的表达式返回一个布尔值(True或False)。所以基本上检查第一个和最后一个字母是否相同。
  3. 并使用从字符串中删除的第一个和最后一个字母再次返回函数的结果。
  4. 令我困惑的是return s[0] == s[-1] and isPal(s[1:-1])位。我不确定我理解根据第一个表达式返回True / False意味着返回函数。老实说,我甚至不确定返回函数实际意味着什么,我猜它只是再次运行函数,但实际上并没有返回任何值。我也不明白这是如何实际判断一个字符串是否是回文。它是不是只是继续击中return s[0] == s[-1] and isPal(s[1:-1])的第二部分,直到字符串,无论是否是回文,是否减少到1或0个字符?我唯一能想到的是从return s[0] == s[-1]返回一个假值,退出函数返回false?但我觉得这实际上并不是Python的工作原理,至少在我的研究中到目前为止我还没有碰到任何说法,在函数中返回一个False会阻止return语句的第二部分执行,这会调用无论第一个和最后一个字母是否相同,该函数都会再次出现。

    此时我正好碰头撞墙,所以任何见解都会非常感激!

4 个答案:

答案 0 :(得分:3)

也许最好的方法是一步一步地使用令您困惑的那一行的值。

return s[0] == s[-1] and isPal(s[1:-1])

假设您正在测试的字符串是“ABCDBA”,这是调用序列

return s[0] == s[-1] and isPal(s[1:-1]) #evaluate to ("A" == "A" and isPal("BCDB")) - need to go deeper
return s[0] == s[-1] and isPal(s[1:-1]) #evaluate ("B" == "B" and isPal("CD")) - need to go deeper
return s[0] == s[-1] and isPal(s[1:-1]) #returns ("C" == "D")

请注意,在最后一行中,由于短路,我们没有评估isPal - 我们知道其中X可以为True或False的False and X始终为False。详细了解here

在最后一行,我们在isPal深入了4个函数。由于最后一行不需要我们再次评估isPal(),我们开始“上升到表面”回到原来的isPal调用

def isPalindrome(s):
    """Returns True if s is a palindrome and False otherwise"""
    return isPal(toChars(s))

答案 1 :(得分:1)

一个澄清可以帮助您了解正在发生的事情:return ...X and ...Y表示:计算X的值。如果值为false,则返回它,否则计算Y的值,并返回它。

有关Python中andor运算符的短路,懒惰行为(即不评估Y,如果不需要)的更多信息:https://docs.python.org/release/2.7/reference/expressions.html#boolean-operations

因此该语句不会使函数返回两个值(X和Y),而是一个值,即X和Y的逻辑AND:如果X和Y都是(计算为),则为真。

还值得将功能函数调用区分开来。可以有许多对同一函数的活动调用,具有不同的参数,局部变量等,因此它们的返回值也可以不同(一旦它们返回)。当函数调用自身时,称为递归。当函数调用返回时,执行在调用者中继续,在递归的情况下,调用者可以是相同的函数(当然是不同的上层函数调用)。

答案 2 :(得分:0)

如果使用print语句在"heeeeh"上运行isPal函数:

def isPal(s):
    if len(s) <= 1:
        return True
    else:
        print s[0],s[-1]
        return s[0] == s[-1] and isPal(s[1:-1])

print isPal("heeeeh")

你得到:

h h
e e
e e
True

因为每个递归调用,索引s[0]s[-1]中的每个字符都相等,因为字符串是回文。

"aeeee"

上运行它
def isPal(s):
    if len(s) <= 1:
        return True
    else:
        print s[0],s[-1]
        return s[0] == s[-1] and isPal(s[1:-1])

print isPal("aeeeeh")

你得到:

a h
False

一旦s[0]s-[1]不相等,函数就会结束并返回False,因为如果字符不相等,它就不能成为回文。

答案 3 :(得分:0)

我会添加我的解释,也许这会对你有帮助。

首先要做的事情:

def toChars(s):
    import string
    s = string.lower(s)
    ans = ''
    for c in s:
        if c in string.lowercase:
            ans = ans + c
    return ans

只需要一些文字并将其全部转换为小写,逐个字符。

接下来是:

def isPal(s):
    if len(s) <= 1:
        return True
    else:
        return s[0] == s[-1] and isPal(s[1:-1])

要理解这一部分,你会问自己一个问题,什么是回文以及如何知道单词或句子是否为一个。

在这个示例中,方法是:回文是单词或句子,其中从开头到结尾的相同距离的字符是相同的字符。

那怎么检查呢?好吧,首先,如果你的单词只是一个字母或更短,那么它就是一个回文。

然后检查单词开头和结尾的字母是否相同。 您记住结果为真或假,并从已检查的字母中删除您的单词并重复此过程,直到您的单词长度为1个或更少,并检查每个比较结果是否为真。

示例:

Foob->foob
f=b? NO, false

示例2:

Fbof->fbof
f=f? Yes, true,
bo
b=o? No, false.

true and false = false, so the word is not a palindrome

示例3:

Fobof->fobof
f=f? Yes, true,
obo,
o=o? Yes, true
b
len(b) = <=1 ? Yes, true,

true and true and true = true, so the word is a palindrome.

希望它有所帮助,问你是否需要更彻底的解释,我会尽力帮助,不用担心,我也会在开始时努力进行递归。