关于python:了解递归和多个返回

Understanding Recursion and Multiple Returns

我正在努力通过麻省理工学院6.00课程的开放式课件,我有点麻烦在递归的讲座。我想我理解基本的想法,你可以把一些问题分解成更小的,可重复的问题。我遇到的问题是理解这在实际代码中是如何工作的。有一个具体的例子我不太明白…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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的工作方式有点迷茫。这是我读到的步骤…

  • 检查s是否为一个字符或更少,是否返回true。
  • 如果s有多个字符,则返回表达式中比较第一个字符和最后一个字符的布尔值(true或false)。所以基本上检查第一个字母和最后一个字母是否相同。
  • 并返回函数再次运行的结果,其中第一个字母和最后一个字母将从字符串中删除。
  • 让我困惑的是return s[0] == s[-1] and isPal(s[1:-1])位。我不确定我是否理解基于第一个表达式返回true/false并返回函数意味着什么。老实说,我甚至不知道返回函数实际上意味着什么,我猜想它只是再次运行函数,但实际上并不返回任何值。我也不明白这是如何判断一个字符串是否是回文的。它会不会一直敲击EDOCX1的第二部分(0),直到字符串(不管它是否是回文)减少到1或0个字符?我能想到的唯一一件事是从return s[0] == s[-1]返回一个假值并返回false退出函数?但我不认为这就是Python的工作原理,至少在我的研究中,到目前为止,我还没有遇到过这样的说法,即在函数中返回一个false将阻止返回语句的第二部分的执行,这将再次调用该函数,而不管第一个和最后一个字母在哪里相同。

    在这一点上,我的头撞在墙上,所以任何洞察都会受到赞赏!


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

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

    假设您要测试的字符串是"abcdba",下面是调用序列

    1
    2
    3
    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可以是真的或是假的False and X总是假的。在这里了解更多。

    在最后一行,我们有4个函数深入到isPal中。由于最后一行不要求我们重新评估isPal(),我们开始"上升到表面",回到最初的isPal调用,它在

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


    有一个解释可以帮助您理解发生了什么:return ...X and ...Y的意思是:计算x的值。如果该值为假,则返回该值,否则计算y的值,然后返回该值。

    关于python中andor运算符的短路、延迟行为(即,如果不需要,不评估y)的更多信息:https://docs.python.org/release/2.7/reference/expressions.html boolean operations

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

    另外,函数调用和函数调用也有区别。同一个函数可以有许多活动调用,其中包含不同的参数、局部变量等,因此它们的返回值也可以是不同的(一旦返回)。当函数调用自身时,这称为递归。当函数调用返回时,调用方继续执行,在递归的情况下,调用方可以是相同的函数(当然是不同的高层函数调用)。


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

    首先要做的是:

    1
    2
    3
    4
    5
    6
    7
    8
    def toChars(s):
        import string
        s = string.lower(s)
        ans = ''
        for c in s:
            if c in string.lowercase:
                ans = ans + c
        return ans

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

    接下来是:

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

    为了理解这一部分,你问自己一个问题,什么是回文,以及知道单词或句子是一个词或句子的方法。

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

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

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

    例子:

    1
    2
    Foob->foob
    f=b? NO, false

    例2:

    1
    2
    3
    4
    5
    6
    Fbof->fbof
    f=f? Yes, true,
    bo
    b=o? No, false.

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

    例3:

    1
    2
    3
    4
    5
    6
    7
    8
    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.

    希望有帮助,问你是否需要更深入的解释,我会尽力帮助你,不用担心,我在开始的时候也在和递归作斗争。


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

    1
    2
    3
    4
    5
    6
    7
    8
    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")

    你会得到:

    1
    2
    3
    4
    h h
    e e
    e e
    True

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

    "aeeee"上运行:

    1
    2
    3
    4
    5
    6
    7
    8
    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")

    你会得到:

    1
    2
    a h
    False

    只要s[0]s-[1]不相等,函数就结束并返回False,因为如果chars不相等,它就不能是回文。