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

Why does Python have a limit on the number of static blocks that can be nested?

Python中静态嵌套块的数量限制为 20。 也就是说,嵌套 19 个 for 循环会很好(尽管非常耗时;O(n^19) 太疯狂了),但嵌套 20 个会失败:

SyntaxError: too many statically nested blocks

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

在此处查看答案:too many statically nested blocks python 您不能增加它,因为它内置于 python 语法中。该限制适用于任何类型的代码堆栈(异常、循环等),并且是设计者的决定(大概是为了保持合理的内存使用)。 一件奇怪的事情是这里:https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Include/code.h#L95 它说 20 是函数 中的最大数字 。但我只是尝试嵌套 23 个 for 循环,而不是在一个函数中,你仍然得到错误。

这跟blockstack有关,是字节码地址的栈,用来执行循环、异常等代码块

碰巧 C 的一个版本(早于 C99)将此限制设置为 20,并且由于 CPython 解释器是用 C 构建的,the same convention has been followed :

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

常量 20 似乎不符合惯例,仅此而已。

[链接由 Christian Dean 提供。]


为什么限制是 20?

如果约定俗成的说法没有说服力,那就看看Python的禅宗:

In [4]: import this
The Zen of Python, by Tim Peters

...
Flat is better than nested.
...

如何增加这个值?

因为这个值是一个硬编码常量,改变它在你的程序中生效的唯一方法是重建你的 python 发行版和 运行 你的脚本在新版本上。

  1. github

  2. 下载cpython源代码
  3. 导航到 cpython/Include/code.h

  4. CO_MAXBLOCKS 的值更改为大于 20

  5. 的值
  6. 重新编译Python(禁用测试,they'll complain

此限制不仅适用于 for 循环,还适用于所有其他控制流块。嵌套控制流块的数量限制在 code.h 内部定义,常量名为 CO_MAXBLOCKS:

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

此常量用于设置堆栈的最大大小 Python 用于执行名为 blockstack 的异常和循环。此限制适用于所有框架对象,并显示在 frameobject.h:

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

此限制的最可能原因是在执行嵌套块时将内存使用保持在合理的水平。它可能类似于 the limit Python imposes on recursive calls. This limit can be seen being enforced in compile.c:

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

关于为什么 Python 有这个特定限制以及为什么他们不能摆脱它的更具体的答案,由 Michael Hudson in a 2004 Python mailing list letter 给出:

Spot on. This has to do with the 'blockstack', very much an internal detail to Python's implementation. We'd like to get rid of it (not because we want to let people write code with more than 20 nested for loops :-) but it's not especially easy (finally: blocks are the biggest problem).

请注意,在 Python 2.6 及更低版本中,打破最大嵌套循环数会导致 SystemError 而不是 SyntaxError。然而,这在 Python 3 中发生了变化,并回溯到 Python 2.7,因此会引发 SyntaxError。这记录在 #issue 27514:

Issue #27514: Make having too many statically nested blocks a SyntaxError instead of SystemError.

异常类型发生这种变化的原因由 Serhiy Storchaka 给出:

[...] SystemError is not an exception that should be raised. SystemError is for errors that can't be occurred in normal case. It should only be caused by incorrect use of C API or hacking Python internals. I think SyntaxError is more appropriate in this case [...].