这实际上是一个令人惊讶的有趣功能,我可以看到它为什么让你感到困惑。我假设你正在试图理解整体的功能,而这在这里实际上不会奏效。
现在,这个函数有两个部分 - 处理空白或字符串中只有一个字母的情况,以及处理字符串中至少有两个字母的情况。然而,这是欺骗性的,因为它根据字符串中有多少字母有效地应用不同的操作!
所以让我们以非递归方式来思考函数:如果字符串太短,只返回字符串。否则,应用某些函数两次除了字符串的第一个字符外,然后将第一个字符添加到结果的末尾。不要认为它是相同的功能,只是把它看作是一个未知的功能。
在代码:
def f(s):
if len(s) <= 1:
return s
return other_f(other_f(s[1:])) + s[0]
下了兔子洞:
那么,我们如何定义这个other_f
?让我们来看看它需要对某些字符串长度有什么样的行为。如果len(s)
是2,那么我们知道s[1:]
是一个字符,因此other_f
只会返回s[1:]
。代码:
def f2(s): # For when len(s)==2
#if statement is not used
#return other_f(other_f(s[1:])) + s[0] becomes
#return other_f(other_f(s[1])) + s[0] becomes
#return other_f(s[1]) + s[0] becomes
return s[1] + s[0]
它只是交换两个字母。让我们用字符串'abc'
看到更容易发生了什么事情与下一个:
def f3(s): # For when len(s)==3
#if statement is not used
#return other_f(other_f(s[1:])) + s[0] becomes
#return f2(f2('bc')) + 'a' becomes
#return f2('cb') + 'a' becomes
#return 'bc' + 'a'
return s[1:] + s[0]
因为加到“BC”功能交换他们并应用了两次,功能撤销自身。所以在这种情况下,我们只是把第一个字母放在字符串的末尾。
def f4(s): # For when len(s)==4
#return f3(f3(s[1:])) + s[0] becomes
#return f3(f3('bcd')) + 'a' becomes
#return f3('cdb') + 'a' becomes
#return f3('dbc') + 'a' becomes
#'dbca'
return s[3] + s[1:3] + s[0] # swap first and last letter
def f5(s): # For when len(s)==5
#return f4(f4(s[1:])) + s[0]
#return f4(f4('bcde')) + 'a'
#swapping first and last letter twice just swaps then swaps back
#return 'bcde' + 'a'
return s[1:] + s[0]
所以看起来我们已经有了一个很好的模式会在这里 - 如果字符串有偶数个字母,交换第一和最后一个字母。如果它有奇数个字母,请将第一个字母移到末尾!
...没有。该模式以f5
结尾。如果你用像'abcd ...'这样的字符串运行函数,你可以很容易地看到每个级别如何移动字母。
f | output
----------
f6|'defbca'
f7|'cdbfgea'
f8|'cgefbhda'
f9|'fecihbgda'
因此,大家可以看到,对于更长的串字母加扰相当周围以及比其他第一个字符总是在字符串的结尾结束了。想想最好的方法是(使用一行代码),您已经设法为每个字符串长度编写不同的函数(一些函数的行为方式相同,如f3
和f5
)。每个函数都依赖于它上面的函数,所以因为f6
就很好地随机化了字符串,所以每个函数都应该随机化字符串。
您是否尝试过使用笔和纸?它不是非常复杂,所以我建议你用变量的当前状态绘制你的调用堆栈。你最好自己找出来,而不是有人向你解释。 – amza
@stazima - 因为他已经花了几个小时,所以我认为OP会更好,并且更清楚地解释它,否则他最终会撞到他迄今为止打的墙。 – rmunn