[英]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.