我正在通过麻省理工学院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的运作方式有点失落。这是我正在读它们的步骤......
令我困惑的是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语句的第二部分执行,这会调用无论第一个和最后一个字母是否相同,该函数都会再次出现。
此时我正好碰头撞墙,所以任何见解都会非常感激!
答案 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中and
和or
运算符的短路,懒惰行为(即不评估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.
希望它有所帮助,问你是否需要更彻底的解释,我会尽力帮助,不用担心,我也会在开始时努力进行递归。