【问题标题】:Some Doubts about Recursion in Python关于 Python 中递归的一些疑问
【发布时间】:2020-12-13 21:08:30
【问题描述】:

顺便说一句,它是python中的井字游戏,它是一个sn-p,它处理用户不输入无效代码或不尝试在已经占用的位置添加X或O的问题。 所以在线视频中的讲师说你可以使用while循环来检查上面列出的问题所以我想为什么不使用递归每当用户输入错误而现在它在输出中显示一些奇怪的东西

def handle_turn(player):

    position=input("Chooes a position from 1 to 9: ")
    if position not in ["1","2","3","4","5","6","7","8","9"]:
        print("Invalid Choice")
        handle_turn(player)
    # while position not in ["1","2","3","4","5","6","7","8","9"]:
    #     position=input("iNVALID CHOICE Chooes a position from 1 to 9: ")

    position=int(position)-1
    if board[position]!="_":
        print("you cannot go there")
        handle_turn(player)
    board[position]=player
    display_board()

输出: 罢工>

从 1 到 9 选择一个位置:1
X | _ | _
_ | _ | _
_ | _ | _
从 1 到 9 选择一个位置:2
X | ○ | _
_ | _ | _
_ | _ | _
从 1 到 9 选择一个位置:3
X | ○ | X
_ | _ | _
_ | _ | _
从 1 到 9 选择位置:1
你不能去那里
从 1 到 9 选择一个位置:9
X | ○ | X
_ | _ | _
_ | _ | O
○ | ○ | X
_ | _ | _
_ | _ | O
从 1 到 9 选择位置:1
你不能去那里
从 1 到 9 选择位置:8
○ | ○ | X
_ | _ | _
_ | X | O
X | ○ | X
_ | _ | _
_ | X |哦

【问题讨论】:

  • 您可能想要勾勒出函数调用。一旦一个函数被调用。执行它后面的下一条语句。使用 return 构造来确保递归结束后不再执行代码。

标签: python python-3.x python-2.7 recursion


【解决方案1】:

handle_turn(player) 替换为return handle_turn(player)

说明

为什么这很重要?考虑以下递归函数:

def f(n):
   print(' '*n + 'beginning of call {}'.format(n))
   if n < 5:
     f(n+1)
   print(' '*n + 'end of call {}'.format(n))

执行此函数会得到以下输出:

>>> f(0)
beginning of call 0
 beginning of call 1
  beginning of call 2
   beginning of call 3
    beginning of call 4
     beginning of call 5
     end of call 5
    end of call 4
   end of call 3
  end of call 2
 end of call 1
end of call 0

如您所见,一旦调用 5 的执行结束,流程将返回到调用 4,该调用执行其剩余的语句 print(' '*n + 'end of call {}'.format(n));然后流程返回到调用 3 等。

因为该函数中没有return 语句,所以函数中的所有语句都会被执行。在递归调用f(n+1)之前编写的语句在递归调用之前执行,在递归调用之后编写的语句在递归调用返回后执行。

对于您的函数handle_turn,如果进行了递归调用,您不希望执行该函数的其余部分。为了防止这种情况发生,您可以在递归调用之后立即添加一个 return 语句。考虑:

def g(n):
   print(' '*n + 'beginning of call {}'.format(n))
   if n < 5:
     g(n+1)
     return
   print(' '*n + 'end of call {}'.format(n))

或等效:

def g(n):
   print(' '*n + 'beginning of call {}'.format(n))
   if n < 5:
     return g(n+1)
   print(' '*n + 'end of call {}'.format(n))

这个新函数的输出将是:

>>> g(0)
beginning of call 0
 beginning of call 1
  beginning of call 2
   beginning of call 3
    beginning of call 4
     beginning of call 5
     end of call 5

如您所见,调用 0 到 4 的其余语句未执行,因为 if 内的 return 语句缩短了这些调用的执行。

如果您想练习并享受没有返回语句的递归函数并在递归调用后始终执行所有剩余语句的递归函数,我建议您玩关于由递归函数控制的机器人的游戏“RoboZZle”,您可以玩在线的。最难的谜题大量使用递归函数的这种行为。

尾递归

在上一段中,我说过一行return g(n+1)和两行g(n+1) \\ return是等价的。在大多数语言中,严格来说这并不正确,因为这两个表达式之一使用 tail recursion,而另一个则没有。 Python 根本没有尾递归,所以这个区别在这里并不重要。

一个后果是,您可以预期大量使用递归的程序在 Python 中会相当慢,甚至在某些情况下会崩溃。在您的示例中这不是问题,因为递归取决于用户输入,如果用户是人类,用户将始终比您的程序慢。但如果用户是另一个程序,则可能会出现问题。

【讨论】:

    猜你喜欢
    • 2012-04-02
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2012-12-01
    • 2018-08-04
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    相关资源
    最近更新 更多