对于 CPython 3.7(和以前的 CPython 版本),限制为 20。但这是实现的一个有点随意的特性; Python 语言定义不需要它,其他 Python 实现(至少 Jython)有不同的限制。见下文。
我知道在 C 中限制是 127
这并不准确。 C 标准建议编译器需要能够处理块嵌套深度至少为 127 的程序,但它不提供任何最大嵌套深度。它确实说:
实现应尽可能避免施加固定的翻译限制。
事实上,标准实际上并没有说实现必须能够处理任何具有 127 块嵌套的程序;它说的是,它必须能够处理“至少一个”这样的程序。 (能够处理任何程序都要求很高,因为编译器可能会因程序文本的其他问题而窒息。)
Python 的规定更不明确。
当然,您可以尝试通过不断尝试更深的嵌套级别来找出限制。使用 bash 脚本(见下文)甚至使用 python 很容易生成这样的程序。但这并没有告诉你任何关于抽象语言的信息。它所告诉您的只是您碰巧使用的特定实现的限制。
您可能会在同一语言的新版本、同一语言的不同实现,甚至是不同主机上的同一语言中发现不同的限制。
例如,我使用以下 bash 函数生成示例 python 程序:
genpython () {
"${2:-python}" -c "$(
for ((i=0; i<$1; ++i)); do
printf "%*sfor i%d in range(1):\n" $i "" $i;
done;
printf '%*sprint("Nested %d worked!")\n' $1 "" $1;
)"
}
生成的程序看起来像(使用genpython 10):
for i0 in range(1):
for i1 in range(1):
for i2 in range(1):
for i3 in range(1):
for i4 in range(1):
for i5 in range(1):
for i6 in range(1):
for i7 in range(1):
for i8 in range(1):
for i9 in range(1):
print("Nested 10 worked!")
Python2 (CPython 2.7.15rc1) 和 Python3 (CPython 3.6.7) 均以 20 位居榜首:
$ genpython 20 python2
Nested 20 worked!
$ genpython 21 python2
SyntaxError: too many statically nested blocks
$ genpython 20 python3
Nested 20 worked!
$ genpython 21 python3
SyntaxError: too many statically nested blocks
但是,jython (2.7.1) 能够达到 99(失败并出现堆栈跟踪而不是简单的语法错误):
$ genpython 99 jython
Nested 99 worked!
$ genpython 100 jython
java.lang.ArrayIndexOutOfBoundsException: Index 100 out of bounds for length 100
at org.python.antlr.PythonTokenSource.push(PythonTokenSource.java:323)
at org.python.antlr.PythonTokenSource.handleIndents(PythonTokenSource.java:288)
at org.python.antlr.PythonTokenSource.insertImaginaryIndentDedentTokens(PythonTokenSource.java:222)
at org.python.antlr.PythonTokenSource.nextToken(PythonTokenSource.java:143)
at org.antlr.runtime.CommonTokenStream.fillBuffer(CommonTokenStream.java:119)
at org.antlr.runtime.CommonTokenStream.LT(CommonTokenStream.java:238)
at org.python.antlr.PythonParser.file_input(PythonParser.java:560)
at org.python.antlr.BaseParser.parseModule(BaseParser.java:77)
at org.python.core.CompileMode$3.dispatch(CompileMode.java:22)
at org.python.core.ParserFacade.parse(ParserFacade.java:158)
at org.python.core.ParserFacade.parse(ParserFacade.java:203)
at org.python.core.Py.compile_flags(Py.java:2205)
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:267)
at org.python.util.jython.run(jython.java:394)
at org.python.util.jython.main(jython.java:142)
java.lang.ArrayIndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException: Index 100 out of bounds for length 100
出于好奇,我尝试用 C 语言做同样的事情,使用稍微修改的脚本:
genc () {
{
echo '#include <stdio.h>'
echo 'int main(void) {';
for ((i=0; i<$1; ++i)); do
printf "%*s for (int i%d=0; i%d==0; ++i%d) {\n" $i "" $i $i $i;
done;
printf '%*s puts("Nested %d worked!");\n' $1 "" $1;
for ((i=$1; i-->0; 1)); do
printf "%*s }\n" $i "";
done;
echo ' return 0;'
echo '}'
} | ${2:-gcc} "${@:3}" -std=c11 -x c - && ./a.out
}
这会产生,例如:
#include <stdio.h>
int main(void) {
for (int i0=0; i0==0; ++i0) {
for (int i1=0; i1==0; ++i1) {
for (int i2=0; i2==0; ++i2) {
puts("Nested 3 worked!");
}
}
}
return 0;
}
(请注意,C 中的嵌套深度比嵌套的 for 语句的数量大一,因为 int main() {...} 也很重要。所以虽然上面说它的嵌套深度为 3,但实际上是深度 4。)
使用 gcc (v8.3.0),我的嵌套深度达到了 15000。我没有进一步尝试,因为编译时间和内存使用已经失控。但是 clang (v7.0.0) 更早地产生了一个错误,尽管有一个建议的解决方法:
$ genc 255 clang
Nested 255 worked!
$ genc 256 clang
<stdin>:258:291: fatal error: bracket nesting level exceeded maximum of 256
...for (int i255=0; i255==0; ++i255) {
^
<stdin>:258:291: note: use -fbracket-depth=N to increase maximum nesting level
1 error generated.
使用建议的命令行选项,我能够可靠地达到 3574 的嵌套深度(即 3573 个嵌套 for 循环)。但比这更高,事情开始不一致地失败。深度 3575 大约有三分之一的尝试失败。深度 3576 失败的时间大约有一半。深度 3577 大约有 80% 的时间失败。失败可能是编译器错误(至少,这是编译器在长堆栈跟踪和更长的错误消息列表后打印出来的)。