无论我用Python visualizer运行多少次,我都无法弄清楚这段代码是如何工作的;有人请告诉我以下代码的递归如何工作?
def reverse_strings(string):
if len(string) == 0: return ''
else: return reverse_strings(string[1:]) + string[0]
reverse_strings('hello')
我自己写了,它有效,但我不知道它是如何工作的。我知道返回递归是通过运行" ello"进入递归函数,但我不能理解它是如何向后打印的。
答案 0 :(得分:1)
递归的概念是你在遇到基本情况之前调用相同的函数。在您的情况下,基本情况是len(string) == 0
时,您向调用者返回一个空字符串,这是同一函数
reverse_strings
的先前版本,但具有不同的参数(通常是一个更“复杂”的功能。)
假设您有这个简单的字符串hi
,您的函数将表现如下:
检查是否到达基本情况,如果是,则返回空字符串,否则转到下一个语句。由于我们没有空字符串,因此我们转到下一个语句。
下一个语句调用相同的函数reverse_strings
,但参数不同于第一次调用它时的参数;事实上,当你第一次打电话时,你会做这样的事情reverse_strings('hi')
。在else
中,您使用较小版本的字符串hi
调用该函数,请参阅以下语句:return reverse_strings(string[1:]) + string[0]
string[1:]
只是i
。现在,基本上你有return reverse_strings('i') + string[0]
。请注意,string[0]
为H
。在这里,reverse_strings('i')
,正如我上面所说,你再次调用你的函数,但你的字符串i
的版本较小。
现在,我们在另一个函数调用中。评估第一个语句if len(string) == 0: return ''
。这是真的吗?不,因为len(string)
仍然与0
不同。所以我们转到下一个语句else: return reverse_strings(string[1:]) + string[0]
。现在,请注意我们将再次调用相同的函数。但是使用较小的字符串,在本例中为空字符串,因为string[1:]
的{{1}}是一个空字符串。因此,我们的通话可以概括为i
。
我们现在处于return reverse_strings('') + i
的另一个“简化版本”。第一个语句被评估reverse_strings
。这是真的吗?是的,因为,请记住,我们的字符串现在是一个空字符串。现在发生的是你将一个空字符串返回给调用者,这是第3点中的函数。
现在,我们刚刚在第3点向调用者返回一个空字符串,因此我们有if len(string) == 0: return ''
。 return '' + i
只不过是简单'' + i
,你将在指针3处返回此函数的调用者,这是第2点的函数。
现在,您刚刚向调用方返回了i
,特别是您刚刚将i
返回到此语句i
,其中return reverse_strings('i') + string[0]
为{{1}您刚刚返回的string[0]
和H
只是reverse_strings('i')
。所以,现在你有i
,你刚刚颠倒了字符串。
答案 1 :(得分:0)
它使用切片将第一个字母连接到结尾,然后再将第二个字母传递给递归函数。
答案 2 :(得分:0)
string[1:]
ello
string[0]
为h
:
第二次递归通话string[1:] -> llo
string[0] -> e
第3 string[1:] ->
个string[0] -> l
第4 string[1:] ->
o string[0] -> l
第五string[1:] ->
“”string[0] -> o
所以reverse_strings(string[1:])
调用函数递归移过字符串,string[0]
连接从结尾开始的每个字母,这是最后返回的结果。
下图可能有所帮助:
答案 3 :(得分:0)
要真正理解这一点,我会以声明的,逻辑的形式表达它。 这是您的代码:
1: if len(string) == 0: return ''
2: else: return reverse_strings(string[1:]) + string[0]
我会调用字符串的第一个元素(string[0]
),其 head ,其余部分(string[1:]
)调用 tail 。如果一个字符串只有1个字符长,我们认为它的尾部是空字符串。就这个词汇而言,这里是反转字符串意义的规则:
如果是abcd
,我们会应用规则2,因为规则1不适用:
abcd
撤消bcd
撤消,然后a
。好的,bcd
反转了什么?好吧,我们可以应用相同的规则:
bcd
撤消cd
撤消,然后b
。并向下链:
cd
撤消d
撤消,然后是c
,d
撤消''
撤消,然后是d
,''
反转为''
,因为它是空字符串。回到这个列表,你得到:
''
后跟d
,然后是c
,然后是b
,后跟a
是dcba
,这就是我们想要的!
围绕递归来解决问题并不容易。尝试用它解决一些其他问题或做一些需要它的练习;这种做法确实有助于理解。