这个函数对我来说没有任何意义。我到处都添加了打印语句来弄清楚到底是怎么回事,但我还是不明白。如果有人能给我解释一下,我将不胜感激。
def f(s):
if len(s) <= 1:
return s
return f(f(s[1:])) + s[0]
print(f("mat"))
这就是我所看到的情况。因此,我们从长度为3的字符串开始,绕过if语句。我们首先处理内部的f(s1:)。所以现在我们有一个长度为2的字符串("at"),它再次绕过if语句并进入f(s1),它给出了长度为1 ( "t“)的字符串,最终进入if语句并返回”t“。对我来说,这就是线索停止的地方。
从我的print语句中,我看到创建了一个长度为2的新字符串,并返回随后的"a“。最终的产品是"atm“。多亏了"+ s“部分,我得到了末尾的"m”标记,但为什么是"atm“而不是"tam"?
老实说,我已经在这上面花了几个小时,但我不能让它下雨。任何帮助都将不胜感激。
发布于 2015-06-20 05:40:40
通过在函数调用中填充它们正在做的事情,将整个过程扩展到很长的步骤中。从最深处/最深处开始处理括号。在加法前处理函数调用。
为了清楚起见,我将忽略所有地方的字符串引号。
f(mat) -> mat is 3 chars:
call f on at for f(at), and call f on that.
add m.
f(f(at))+m -> inner f(at), at is 2 chars:
call f on t for f(t), and call f on that.
add a.
f(f(f(t))+a)+m -> innermost f(t) returns t.
f(f(t)+a)+m -> inner f(t) returns t as well.
f(ta)+m -> [here, the first f(f(at)) has been reduced to f(ta)]
ta is 2 chars:
call f on a for f(a), and call f on that.
add t.
f(f(a))+t+m -> inner f(a) returns a.
f(a)+t+m -> f(a) returns a as well.
a + t + m ->
atm -> everything reduces to atm.
发布于 2015-06-20 05:06:48
简而言之:a
和t
交换了两次,因此内部f("at")
调用返回"ta"
,然后外部f()
调用传递"ta"
并返回"at"
。
更长的版本:我不会明确地为你解释,因为你不会学到那么多东西,但考虑这个函数,它是完全等价的
def f2(s):
if len(s) <= 1:
return s
x = f2(s[1:])
return f2(x) + s[0]
print(f2("mat"))
当您调用f2("mat")
时,s[1:]
为"at"
。现在,f2("at")
返回什么呢?将该值(x
的值)插入到f2(x) + s[0]
表达式中,看看会得到什么。
尝试遍历f2("at")
和f2("ta")
的值,看看是否能发现发生了什么。如果你在另一个15-20分钟的工作后仍然需要帮助,请评论这个答案,我将进一步扩展它。
发布于 2015-06-20 06:30:16
这实际上是一个令人惊讶的有趣的函数,我可以理解为什么它会让您感到困惑。我假设您试图将函数作为一个整体来理解,而这在这里实际上不会很好地工作。
现在,这个函数有两个部分-处理它为空或字符串中只有一个字母的情况,以及处理字符串中至少有两个字母的情况。然而,这是欺骗性的,因为它根据字符串中有多少个字母有效地应用了不同的操作!
因此,让我们以一种非递归的方式来考虑这个函数:如果字符串太短,就返回该字符串。否则,将某个函数应用于字符串中除第一个字符之外的所有字符两次,然后将第一个字符添加到结果的末尾。不要认为它是同一个函数,只要把它看作是某个未知的函数就行了。
在代码中:
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
on down可以很好地随机化字符串,所以每个后续函数也应该很好地随机化字符串。
https://stackoverflow.com/questions/30947216
复制相似问题