为什么我需要rreverse函数的两个条件分支?

Hil*_*ani 5 python recursion python-3.x

我做了一个练习,试图在另一个人的问题上使用我在这里找到的代码部分,但我发现我需要一部分代码,我不知道为什么要这样做.

我用于我的函数的完整代码是这样的:

def rreverse(s):
    if s == "":
        return s
    else:
        return rreverse(s[1:]) + s[0]
Run Code Online (Sandbox Code Playgroud)

但是我只使用了else作为声明,而我没有得到我希望得到的结果.

def recur_reverse(x):
    if x != "":
        return recur_reverse(x[1:]) + x[0]
Run Code Online (Sandbox Code Playgroud)

我得到TypeError说"不支持的操作数类型为+:'NoneType'和'str'."

第一个例子正常工作的逻辑是什么,第二个例子在这个if语句的差异时抛出错误是什么?为什么我的版本不正确?

谢谢!

Jea*_*bre 6

第二个结构的问题是if s是空字符串,函数返回None的不是字符串,而end-caller 需要一个字符串,甚至是空的,所以返回None会使调用者代码中断(这导致像为什么我的函数返回None?)

你可以用三元表达式来编写它,以确保它返回任何值的值 x

def recur_reverse(x):
    return recur_reverse(x[1:]) + x[0] if x else ""
Run Code Online (Sandbox Code Playgroud)


bru*_*ers 5

当Python函数在没有显式return语句的情况下到达它的最后一个语句时,它会隐含地返回None.在你的第二个例子中:

def recur_reverse(x):
    if x != "":
        return recur_reverse(x[1:]) + x[0]
Run Code Online (Sandbox Code Playgroud)

x实际上是空字符串时,if跳过分支并继续执行"下一个语句" - 但由于没有"下一个语句"(你已到达函数的结尾),函数返回None.使用递归调用,您总是最终使用空字符串调用该函数,因此该函数返回None,并且如错误消息所示,您不能None与字符串连接(出于非常明显的原因).


Wil*_*sem 4

在递归中,您每次从字符串中“弹出”第一个元素,并将其附加到其余元素的相反位置。s[0]srreverse(s[1:])

但这意味着我们最终将使用空字符串进行调用(因为字符串具有固定的长度,如果我们每次弹出一个字符,最终我们将用完字符)。

空字符串没有一个字符s[0],因此这将引发IndexError,以防止我们将空字符串实现为基本情况:空字符串的反向是空字符串。所以:

def rreverse(s):
    if s == "":  # empty string (base case)
        return s
    else:        # non-empty string (recursive case)
        return rreverse(s[1:]) + s[0]
Run Code Online (Sandbox Code Playgroud)

如果您不实现这种情况,则存在一个没有显式返回表达式的代码路径。如果函数没有显式返回某些内容,Python 将返回None

但请注意,我们进行rreverse(s[1:])调用,如果返回 in None,我们将因此将None和 一个字符串(例如'a')添加在一起。但这没有意义:Python 不知道如何添加 aNone和字符串(好吧,这样做没有意义),因此会出现错误。

因此,您的版本将用于rreverse('ab')像这样的调用(不是有效的Python,只是为了演示问题):

# second version
rreverse('ab')
  -> rreverse('b') + 'a'
       -> rreverse('') + 'b'
            -> None
          None + 'a'  ==> TypeError
Run Code Online (Sandbox Code Playgroud)

而对于第一个版本:

# first version
rreverse('ab')
  -> rreverse('b') + 'a'
       -> rreverse('') + 'b'
            -> ''
          '' + 'b'
          'b'
     'b' + 'a'
     'ba'
Run Code Online (Sandbox Code Playgroud)