繁体   English   中英

这个递归如何在python中工作?

[英]How does this recursion work in python?

几个小时前我在python的递归中观看了一段视频,然后重新创建了在视频中制作的程序,因此它在我的Python版本中运行。 代码可以工作,但有一点我不完全理解它正在做什么。

def lower(s):
    s = s.lower()
    return s

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

def isPalindrome(s):
    if isPal(lower(s)) == True:
        print("{0} is a palindrome".format(s))

我遇到问题的部分是

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

我想知道为什么他们被退回,为什么它是[1:-1]而不是s [0:-1]如果你认为你知道任何有助于简化递归的好地方我随意分享他们。 提前致谢。

为什么它是[1:-1]而不是s [0:-1]

s[1:-1]返回s ,第一个和最后一个元素被切掉。 s[0:-1]返回s ,最后一个元素被切断。

您需要切断两端以保持回文性质(如果它是回文),即与中间等距的元素是相同的。 如果你只切断一端,你移动中间,这将(在一般情况下)破坏该不变量。

这是自我递归的核心:你做了一件事,然后你委托一个具有相同属性的简单案例。

为什么返回s [0] == s [-1]和isPal(s [1:-1])

这是因为它首先检查第一个和最后一个元素是否具有回文属性(如上所述)并且下一个“图层”也具有该属性。 如果外部对不相等则不是回文,并且将返回False ; 如果为true,则执行递归步骤,如果为True,则表达式返回True

想象一下你有“皮划艇”这个词

该程序将查看是否:

'k' == 'k'如果是,程序将调用该函数: 'aya'

然后程序将查看'a' == 'a'如果是,程序将使用'y'调用该函数

然后它只有一个字母,所以程序返回True

这就是魔术发生的地方:

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

(我添加了括号,因此您对运算符优先级非常清楚)。 重要的是要知道Python AND语句将评估第一个参数,并且只有当它为True ,它才会评估第二个参数。 如果第一个是False ,那么它将立即返回False而不调用isPal() 这被称为短路评估 Blender在他的帖子中就是一个很好的例子。

s[0]是字符串中的第一个字母, s[-1]是sting中的最后一个字母。 首先,我们检查第一个和最后一个字母是否相同。 如果它们不同,则字符串无法成为回文。 如果它们是相同的,我们可以忽略它们并移动到字符串的内部。

s[1:-1]修剪掉第一个和最后一个字母,然后将其传递给isPal()函数,该函数恰好是我们当前所在的函数 - 这称为递归。 当我们再次“进入”函数时,会创建一个新的堆栈,创建新的局部变量,并且该函数的输入参数将与前一次调用中的参数不同。

我们继续检查第一个和最后一个字母,并一直递归到单词的中心。 在这一点上,还剩下1或0个字符,如果我们已经到了那么远,我们知道我们找到了一个回文。

当我们从最终的内部返回时,调用isPal()返回值(如果找到了回文,则为True )被传递给调用函数,然后调用函数将其返回到其调用函数等,直到最后的'外部' isPal()函数将结果返回给初始调用者。 我们将此过程称为“展开堆栈”。

这是一个例子:

s = 'racecar'
s[0] == s[-1] # True - both letters are 'r'
s = s[1:-1]   # s becomes 'aceca'
s[0] == s[-1] # True - both letters are 'a'
s = s[1:-1]   # s becomes 'cec'
s[0] == s[-1] # True - both letters are 'c'
s = s[1:-1]   # s becomes 'e'
len(s) <= 1   # This statement is now True, so the stack will start to unwind

在视觉上,调用将如下所示:

'racecar' ---------
                  |
                  V    'aceca'
 True <--- isPal(   ) ----
             ^           |
        True |           V     'cec'
             ---- isPal(   ) ----
                    ^           |
               True |           V     'e'
                    ---- isPal(   ) ----
                           ^           |
                      True |           V
                           ---- isPal(   )  # We get all the way down here,
                                            # and then we start to return

在我们没有回文的情况下,这将发生:

'race2car' --------
                  |
                  V    'ace2ca'
False <--- isPal(   ) ----
             ^           |
       False |           V     'ce2c'
             ---- isPal(   ) ----
                    ^           |
              False |           V     'e2'
                    ---- isPal(   ) ----
                           ^           |
                     False |           V
                           ---- isPal(   )  # Here the outer two letters
                                            # do not match, so we start to
                                            # return False

你正在检查s的第一个和最后一个是否相同,所以一旦你这样做,你将它们切掉并通过返回递归部分检查下一个和最后一个是否相同,并且它一直将结果加在一起直到那里是s中的1个或更少的字母。 然后它返回到目前为止收集的内容和True。

if len(s) <= 1:print(s[0] == s[-1] and isPal(s[1:-1]))else:之后在行上添加print(s) else:可能会帮助您更多地理解递归。

该步骤使用短路逻辑AND,因此它的行为如下:

if s[0] != s[-1]:
    return False
else:
    return isPal(s[1:-1])

至于s[1:-1] ,你将第一个和最后一个字符与s[0] != s[-1] ,所以s[1:-1]只删除第一个和最后一个字符并传递结果字符串回到isPal

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM