为什么Python对可以嵌套的静态块的数量有限制?

Python中静态嵌套块的数量限制为20个。也就是说,嵌套19 for循环将会很好(虽然过于耗时; O(n^19)是疯狂的),但是嵌套20将会失败:

 SyntaxError: too many statically nested blocks 

有这个限制的根本原因是什么? 有没有办法增加限制?

此限制不仅适用for循环,也适用于所有其他控制stream程块。 嵌套控制stream程块的数量限制是在code.h中用名为CO_MAXBLOCKS的常量CO_MAXBLOCKS

 #define CO_MAXBLOCKS 20 /* Max static block nesting within a function */ 

这个常量用于设置Python用于执行exception和循环的最大大小,命名为blockstack 。 这个限制被强加在所有的框架对象上,并显示在frameobject.h中 :

 int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ 

这个限制的最可能的原因是在执行嵌套块时将内存使用保持在一个合理的水平。 这可能类似于Python对recursion调用的限制 。 这个限制可以看作是在compile.c中强制执行的:

 if (c->u->u_nfblocks >= CO_MAXBLOCKS) { PyErr_SetString(PyExc_SyntaxError, "too many statically nested blocks"); return 0; } 

Michael Hudson在2004年的Python邮件列表中写道 :为什么Python有这个特定限制以及为什么他们不能摆脱它,更具体的答案是:

发现。 这与'blockstack'有关,这是Python实现的一个内部细节。 我们希望摆脱它( 不是因为我们想让人们编写超过20个嵌套for循环的代码:-),但并不是特别容易(最后:块是最大的问题)。

请注意,在Python 2.6及更低版本中,打破嵌套循环的最大数目会导致SystemError而不是SyntaxError 。 然而,这在Python 3中进行了更改,并且已经修补到Python 2.7,所以会引发一个SyntaxError 。 这被logging在#issue 27514 :

问题#27514:使太多的静态嵌套块SyntaxError而不是SystemError。

Serhiy Storchaka给出了这种exceptiontypes变化的原因:

SystemError不是应该提出的例外。 SystemError是针对在正常情况下不能发生的错误。 这应该只是由于错误地使用C API或者黑客使用Python内部引起的。 我认为在这种情况下SyntaxError更合适[…]。

这与blockstack堆栈有关,块堆栈是字节码地址的堆栈,用于执行代码块,例如循环和exception。

恰巧,一个C版本(比C99更早)已经将这个限制设置为20 ,而且由于CPython解释器是用C编译的, 所以遵循了相同的约定 :

 #define CO_MAXBLOCKS 20 /* Max static block nesting within a function */ 

常数20似乎是出于惯例,而不是更多。

[链接礼貌基督教院长。]


为什么是20的限制?

如果公约的论点不能令人信服,那么看一下“ The Python of Zen”

 In [4]: import this The Zen of Python, by Tim Peters ... Flat is better than nested. ... 

你怎么能增加这个价值?

由于这个值是一个硬编码的常量,所以在你的程序中改变它的唯一方法是重build你的python发行版并在新的版本上运行你的脚本。

  1. 从github下载cpython源代码

  2. 导航到cpython/Include/code.h

  3. CO_MAXBLOCKS的值更改为大于20的任何值

  4. 重新编译Python(禁用testing, 他们会抱怨 )

在这里看到答案: 太多静态嵌套块python你不能增加它,因为它是内置的Python语法。 这个限制适用于任何types的代码堆栈(例外,循环等),并且是由devise者决定的(大概是为了保持内存使用合理)。 一个奇怪的是在这里: https : //github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Include/code.h#L95它说20是一个函数中的最大数量。 但我只是试图嵌套23循环,而不是在一个函数内,你仍然得到错误。