Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 递归函数在递归限制之前停止工作。记忆,工作到一个点(2400),但没有结果结束_Python_Recursion - Fatal编程技术网

Python 递归函数在递归限制之前停止工作。记忆,工作到一个点(2400),但没有结果结束

Python 递归函数在递归限制之前停止工作。记忆,工作到一个点(2400),但没有结果结束,python,recursion,Python,Recursion,我的函数只是一个简单的递归加法,带有一条缓存指令,以防止它在递归过程中超出需要。输入4,我们得到1+2+3+4=10。它也会被缓存,这样它就不会超出功能需要,也不会使我的低功耗笔记本电脑过载 如果我输入2200,我将在大约0.2秒内得到正确的结果。但是,每当我输入一个高于2417左右的数字(有时这个数字更高或更低),它都不会给我任何结果,“在2.3s内完成”。没有错误,因为我的递归限制设置高于这个值。我只是。。。没有回答 请注意,这不是关于递归值的问题,也不是关于递归在某些情况下是否合适的问题。

我的函数只是一个简单的递归加法,带有一条缓存指令,以防止它在递归过程中超出需要。输入4,我们得到1+2+3+4=10。它也会被缓存,这样它就不会超出功能需要,也不会使我的低功耗笔记本电脑过载

如果我输入2200,我将在大约0.2秒内得到正确的结果。但是,每当我输入一个高于2417左右的数字(有时这个数字更高或更低),它都不会给我任何结果,“在2.3s内完成”。没有错误,因为我的递归限制设置高于这个值。我只是。。。没有回答

请注意,这不是关于递归值的问题,也不是关于递归在某些情况下是否合适的问题。我发布了一个类似的问题,我得到的唯一答案是“你为什么要使用递归?”这是因为我是新手,只是想学习;)!但是在玩弄我的代码所能做的极限时,我发现很奇怪,我不能用高于2400的整数运行它,尽管我没有得到任何错误

这是我的密码:

recur_cache= {}
def recur_add(n): 
    if n in recur_cache: 
        value = recur_cache[n] 
    if n == 1: 
        value = 1
    if n == 0: 
        value = 0
    else: 
        value = n + recur_add(n-1)


    recur_cache[n] = value
    return value
谢谢

内存限制和递归 你对这个话题的看法是

没有错误,因为我将递归限制设置为100000000,只是。。。没有结果

这样做似乎不会超出计算机的处理能力,那么为什么我会受到这个限制呢

首先,CPython解释器是一个运行在计算机上的进程。操作系统决定进程的处理量,如果超过此限制,操作系统将终止应用程序

也许不用说,但操作系统是在物理限制的真实硬件上运行的,操作系统的任务是控制进程如何与物理资源交互。一个进程不能说“我需要[在这里插入任意数量的]内存页”,并期望该请求得到操作系统的批准或符合硬件施加的物理限制

当您键入python3 my_program.py并点击回车键时,将加载python3进程并从操作系统获取内存。此过程解析源代码,将程序编译为字节码(如果语法正确),并解释字节码。当您的程序执行时,进程有一些有限的空间来处理,既可以存储自己的数据,也可以存储与您的程序相关的数据(您分配的对象、您打开的资源、您调用的函数等)

当应用程序进行函数调用时,解释器需要为堆栈帧留出空间。这个空间不是想象的或理论的。解释器必须从操作系统获得真正的内存。如果该调用生成其他调用,则第一个调用的内存仍处于占用状态,因为在子调用解析后,当它重新获得控制权时,需要它来完成其指令。因此,解释器每次调用都会使用更多的内存,除了在某个点停止递归并开始释放堆栈帧之外,没有办法释放这些内存

CPython内置了一个合理的递归限制来创建安全网。这将作为和向程序员公开。如果有深度递归,则可能出现两种情况。典型的情况是,您的堆栈超出了CPython解释器施加的人工内存限制,解释器会轻轻地抛出一个
递归错误
,并让您处理它(通常通过重新编写程序来修复无限递归错误)

第二种可能性是你告诉CPython解释器“我知道我在做什么,我希望你忽略你对我的程序施加的合理限制”。通过执行
sys.setrecursionlimit(100000000)
,您实际上是在抛开安全网,冒着整个解释器过程崩溃的风险,而解释器过程是一个复杂的过程。作为:

最高可能限制取决于平台。当用户有需要深度递归的程序和支持更高限制的平台时,可能需要将限制设置得更高。这应该小心,因为过高的限制可能会导致崩溃

这里的崩溃不仅仅是解释器创建的某个CPython异常事件,它是解释字节码的正常部分,导致了太多调用;解释器进程耗尽堆栈内存,操作系统终止运行程序的整个进程

我只是。。。没有回答

是的,当操作系统终止一个进程时,就会发生这种情况,此时您返回控制台并返回一个退出状态代码。操作系统没有给解释器提供转储堆栈跟踪或消息的特权

你当然可以,但这样做基本上是一种黑客行为——你可以想出一个足够大的数字,超过堆栈大小,你就回到了你开始掌握一种根本上有缺陷的方法的地方。对于某些应用程序,您可能会发现增加堆栈可以为您购买足够的空间,以实现快速完成非生产任务所需的功能,但请注意,您弄乱的任何旋钮都可能无法移植到其他环境中


回忆录 是一种避免重复工作的缓存技术。如果您的计算密集型函数被要求生成它以前完成的计算结果,它可以查找并返回它

但记忆化并不能超越这一点,它也不会像你所想的那样阻止堆栈溢出。对于第一次调用,表是空的,因此需要分配整个
n
堆栈帧。如果在第一个分支中添加一个打印,当备注表包含上一个计算时触发,您将看到它从不触发。在这种情况下,dict查找只能对后续调用顶级函数有所帮助


使用循环而不是递归 递归不应该应用于大多数问题,对一系列数字求和就是一个很好的例子