递归python3代码中的堆栈溢出

时间:2018-12-18 00:27:03

标签: python-3.x recursion

我试图建立一个简单的代码,使用python解决值n的平方运算,而且,我想学习递归。我制作了三种不同的样式代码,例如以下语法:

第一个代码

def pangkat(nilai, pangkat):
    a = int(1)
    for i in range(pangkat):
        a = a * nilai
    return a

if __name__ == "__main__":
    print(pangkat(13, 8181))

第二个代码

def pangkat(nilai, pangkat):
    hasil = nilai**pangkat
    return hasil

if __name__ == "__main__":
    print(pangkat(13, 8181))

第三代码

def pangkat(nilai, pangkatnilai):
    if pangkatnilai == 1:
        return nilai

    return nilai * pangkat(nilai, pangkatnilai-1)

if __name__ == "__main__":
    print(pangkat(13,8181))

注意:参数nilai是将要引发的数字,pangkat是将要引发参数nilai的数字),例如,当我填写nilaiparam

输入0

pangkat(13, 12)

输出0

23298085122481

当我更改参数pangkat> = 1000时出现了问题,它会说,它将给我一个错误,但仅在第三代码中出现。

Traceback (most recent call last):
  File "pang3.py", line 8, in <module>
    print(pangkat(13,1000))
  File "pang3.py", line 5, in pangkat
    return nilai * pangkat(nilai, pangkatnilai-1)
  File "pang3.py", line 5, in pangkat
    return nilai * pangkat(nilai, pangkatnilai-1)
  File "pang3.py", line 5, in pangkat
    return nilai * pangkat(nilai, pangkatnilai-1)
  [Previous line repeated 995 more times]
  File "pang3.py", line 2, in pangkat
    if pangkatnilai == 1:
RecursionError: maximum recursion depth exceeded in comparison

虽然第一个和第二个代码运行良好。我的递归函数可能会出什么问题?再加上我需要它的解释,谢谢!

NB:是否有可能像我需要的那样使用递归更好的方法?我使用自己的逻辑来构建递归,所以我希望有人能为该代码提供更好的方法。

2 个答案:

答案 0 :(得分:2)

Python解释器限制了递归的深度。默认情况下,深度为1000个级别的函数调用,此后您将获得异常(您从第三个函数中看到的RecursionError)。因此,一方面,您的代码可以按预期工作。您希望递归8181次,而Python在1000后退出,因为这是默认限制。

如果您想更深入地递归,可以使用sys.setrecursionlimit函数来更改递归限制。将递归限制设置为9000就足以使函数使用示例中给出的参数来运行。

关于Python为什么只允许有限的递归深度的原因,主要是因为很少需要更多的递归。在大多数情况下,递归的效率要比迭代低得多,因此您通常不希望对大问题使用深度递归,因为它会非常慢。在大多数情况下,您达到了递归限制,这是因为有一个错误使原本应该从浅层递归变为无限递归,而Python通过停止程序而不是让它永远继续下去,做了正确的事情

答案 1 :(得分:1)

实际上,默认的递归最大深度为 1000 。在这种情况下,要摆脱该问题,您必须在代码顶部使用下面的1行。

sys.setrecursionlimit(1002)

如果您还想尝试其他值(例如, 1050,1400等(在您的情况下也有效)。

sys.setrecursionlimit(1500)

  

访问https://docs.python.org/3/library/sys.html#sys.setrecursionlimit以查看详细信息。在这里,我粘贴要重点关注的重要部分。

     
      
  • 设置要限制的 Python解释器堆栈的最大深度。此限制可防止无限递归导致 C堆栈溢出和崩溃 Python。

  •   
  • 最大可能的限制是与平台有关。当用户拥有需要深度递归的程序和支持更高限制的平台时,他们可能需要将限制设置为更高。这样做应该小心,因为上限太高会导致崩溃

  •   
  • 如果在当前递归深度下新限制太低,则会引发 RecursionError 异常。

  •   
import sys

print(sys.getrecursionlimit()) # 1000
sys.setrecursionlimit(1002)    # Set max depth for recursion
print(sys.getrecursionlimit()) # 1002 (Checing again) 

def pangkat(nilai, pangkatnilai):
    if pangkatnilai == 1:
        return nilai

    return nilai * pangkat(nilai, pangkatnilai-1)

if __name__ == "__main__":
    print(pangkat(13, 1000))