Python 使用递归printReverse字符串的机制
我正在读书 它用一个简单但巧妙的例子Python 使用递归printReverse字符串的机制,python,algorithm,Python,Algorithm,我正在读书 它用一个简单但巧妙的例子printReverse 让我们从一个简单的编程问题开始: 按相反顺序打印字符串 您可以轻松地迭代解决此问题,即从字符串的最后一个字符开始循环字符串。但是递归地解决它怎么样 首先,我们可以将所需函数定义为printReverse(str[0…n-1]),其中str[0]表示字符串中的第一个字符。然后我们可以分两步完成给定的任务: printReverse(str[1…n-1]):按相反顺序打印子字符串str[1…n-1] print(str[0]):打印字符串
printReverse
让我们从一个简单的编程问题开始:
按相反顺序打印字符串
您可以轻松地迭代解决此问题,即从字符串的最后一个字符开始循环字符串。但是递归地解决它怎么样
首先,我们可以将所需函数定义为printReverse(str[0…n-1])
,其中str[0]
表示字符串中的第一个字符。然后我们可以分两步完成给定的任务:
printReverse(str[1…n-1])
:按相反顺序打印子字符串str[1…n-1]
print(str[0])
:打印字符串中的第一个字符import unittest
import logging
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(message)s")
def printReverse(s):
helper(0, s)
def helper(idx, s):
if s == None or idx >= len(s):
return
logging.debug(f"index:{idx}")
helper(idx+1, s)
print(s[idx])
class MyCase(unittest.TestCase):
def test_printReverse(self):
s = 'string'
printReverse(s)
unittest.main()
我对它的工作原理感到非常困惑。特别是第一个s[0]不是s而是g
$ python printReverse.py
DEBUG index:0
DEBUG index:1
DEBUG index:2
DEBUG index:3
DEBUG index:4
DEBUG index:5
g
n
i
r
t
s
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
我已确认调用堆栈正在作为
def printReverse2(s):
stack = []
for c in s:
stack.append(c)
for c in stack:
print(c)
然而,这个过程是隐式的,似乎没有这样的步骤将所有字符放入堆栈,而是立即跳转到对于堆栈中的c,打印(c)
如何设计调试以查看生成调用堆栈的过程?
.您调用
printReverse('string')
它调用helper(0,'string')
。这很清楚
但是我们如何得到结果呢?print(s[idx])
行应该打印s
——第一个字符,对吗?但是等等,Python解释器必须首先执行前一行,即helper(idx+1,s)
执行该语句意味着Python必须弹出该执行的结果值(在您的例子中,helper不返回任何值,即None),事实上,对于t,r,i,n,g
中的每一个,都有一个新的堆栈帧。看起来怎么样
helper(0,'string')
helper(0,'string')
frame等待helper(1,'string')
的结果,然后打印'string'[0]'
,即s
helper(1,'string')
frame等待helper(2,'string')
的结果,然后打印'string'[1]'
,即t
helper(5,'string')
等待helper(6,'string')
helper(6,'string')
有点不同,因为6>=len('string')
。如果触发了,并且它有一个结果None
-它不需要等待任何东西李>
现在helper(5,'string')
得到了helper(6,'string')
的结果,并继续执行print
语句。最后一个字符g
出现在屏幕上
helper(4,'string')
具有helper(5,'string')
的结果,可以继续执行print语句,得到一个n
。。。等等
…直到得到helper(1,'string')
的结果以及原始调用helper(0,'string')
才能打印s
您可以使用该模块暂停Python程序并逐行执行它。对于堆栈中的c来说,这不是,更像是而c=stack.pop()
。项目以后进先出的顺序从堆栈中弹出。换句话说,相反。将所有字符放入堆栈的代码部分是递归调用(helper(idx+1,s)
)。是的,当c=stack.pop()是智能的,并且是PEP 572样式的@BlorgbeardNow,我很清楚他一直在理解尾部递归的堆栈过程helper(idx+1,s)
@BlorgbeardSorry,我不明白这个问题-你能说得更清楚吗?感谢你的详细解释,Brilliant。你无法想象我现在有多高兴。英雄联盟