van - ¿Por qué Python tiene un límite en la cantidad de bloques estáticos que se pueden anidar?
que se puede hacer con python (3)
Este límite no solo se aplica a los bucles, sino también a todos los demás bloques de flujo de control.
El límite para el número de bloques de flujo de control anidados se define dentro de
code.h
con una constante llamada
CO_MAXBLOCKS
:
#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
Esta constante se usa para establecer el tamaño máximo de la pila que Python usa para ejecutar excepciones y bucles llamados
blockstack
.
Este límite se impone a todos los objetos de marco y se muestra en
frameobject.h
:
int blockstack[CO_MAXBLOCKS]; /* Walking the ''finally'' blocks */
La razón más probable para este límite es mantener el uso de memoria en un nivel sensato cuando se ejecutan bloques anidados. Probablemente sea similar al límite que Python impone a las llamadas recursivas . Se puede ver que este límite se aplica en compile.c :
if (c->u->u_nfblocks >= CO_MAXBLOCKS) {
PyErr_SetString(PyExc_SyntaxError,
"too many statically nested blocks");
return 0;
}
Michael Hudson dio una respuesta más concreta de por qué Python tiene este límite específico y por qué no pueden deshacerse de él en una carta de la lista de correo de Python 2004 :
Spot on. Esto tiene que ver con el ''blockstack'', en gran medida un detalle interno de la implementación de Python. Nos gustaría deshacernos de él ( no porque queramos que las personas escriban código con más de 20 bucles anidados :-) pero no es especialmente fácil (finalmente: los bloques son el mayor problema).
Tenga en cuenta que en Python 2.6 y
SystemError
, romper el número máximo de bucles anidados habría causado un
SystemError
no un
SyntaxError
.
Sin embargo, esto fue cambiado en Python 3 y parcheado a Python 2.7 para que se
SyntaxError
un
SyntaxError
.
Esto se documentó en el
número 27514
:
Problema n.º 27514: haga que tener demasiados bloques anidados estáticamente sea un SyntaxError en lugar de SystemError.
La razón de este cambio en los tipos de excepción fue dada por Serhiy Storchaka :
[...] SystemError no es una excepción que deba plantearse. SystemError es para errores que no pueden ocurrir en el caso normal. Solo debe ser causado por el uso incorrecto de la API de C o la piratería interna de Python. Creo que SyntaxError es más apropiado en este caso [...].
El número de bloques anidados estáticamente en Python está limitado a 20. Es decir, anidar 19
for
bucles estará bien (aunque consume demasiado tiempo;
O(n^19)
es una locura), pero anidar 20 fallará con:
SyntaxError: too many statically nested blocks
¿Cuál es la razón subyacente para tener ese límite? ¿Hay alguna manera de aumentar el límite?
Esto tiene que ver con la frameobject.h , que es una pila de direcciones de código de bytes, y se usa para ejecutar bloques de código como bucles y excepciones.
Sucede que una versión de C (anterior a C99) había establecido este límite en
20
, y dado que el intérprete de CPython está construido con C,
code.h
:
#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
La constante
20
parece estar establecida por convención, y nada más.
[Enlaces cortesía de Christian Dean.]
¿Por qué es el límite 20?
Si el argumento de la convención no es convincente, eche un vistazo a The Zen of Python :
In [4]: import this
The Zen of Python, by Tim Peters
...
Flat is better than nested.
...
¿Cómo puedes aumentar este valor?
Dado que este valor es una constante codificada, la única forma de cambiarlo para que tenga efecto en sus programas es reconstruir su distribución de Python y ejecutar su script en la nueva compilación.
-
Navegue a
cpython/Include/code.h
-
Cambie el valor de
CO_MAXBLOCKS
a algo mayor que 20 -
Recompile Python (deshabilite las pruebas, github.com/python/cpython/blob/… )
Vea la respuesta aquí: demasiados bloques estáticamente anidados python No puede aumentarlo ya que está integrado en la sintaxis de python. El límite se aplica a cualquier tipo de pila de código (excepciones, bucles, etc.) y es una decisión de los diseñadores (presumiblemente para mantener un uso razonable de la memoria). Una cosa extraña es que aquí: code.h dice que 20 es el número máximo en una función . Pero acabo de intentar anidar 23 para bucles, no dentro de una función, y aún obtienes el error.