65 votes

Pourquoi Python limite-t-il le nombre de blocs statiques pouvant être imbriqués?

Le nombre de blocs imbriqués statiquement dans Python est limité à 20. Autrement dit, les boucles imbriquées de 19 for iront bien (bien que prendre beaucoup de temps; O(n^19) est insensé), mais imbriquer 20 échouer avec:

 SyntaxError: too many statically nested blocks
 

Quelle est la raison sous-jacente d'avoir une telle limite? Y a-t-il un moyen d'augmenter la limite?

80voto

Christian Dean Points 14809

Cette limite ne s'applique pas seulement à l' for boucles, mais pour tous les autres flux de contrôle blocks. La limite pour le nombre de imbriquée de contrôle de flux de blocs est définie à l'intérieur du code.h avec une constante nommée CO_MAXBLOCKS:

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

Cette constante est utilisée pour définir la taille maximale de la pile Python utilise pour exécuter des exceptions et des boucles nommé blockstack. Cette limite est imposée à tous les objets d'image et est indiqué dans frameobject.h:

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

La raison la plus probable pour cette limite est de garder l'utilisation de la mémoire à un sain niveau lors de l'exécution de blocs imbriqués. C'est probablement similaire à la limite Python impose sur les appels récursifs. Cette limite peut être vu comme étant appliquée à la compilation.c:

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

Plus de réponses concrètes pourquoi Python a ce spécifique limite et pourquoi ils ne peuvent pas se débarrasser de lui, a été donné par Michael Hudson en 2004, un Python liste de diffusion de la lettre:

Spot sur. Cela a à voir avec le "blockstack', très bien dans un intérieur détail de Python de la mise en œuvre. Nous aimerions pour se débarrasser d'elle (pas parce que nous voulons que les gens écrire du code avec plus de 20 for imbriquées boucles :-) mais ce n'est pas spécialement facile (enfin: les blocs sont les plus gros problème).

Notez que dans la version 2.6 de Python et de bas, de casser le nombre maximum de boucles imbriquées serait de provoquer un SystemError pas SyntaxError. Cela a été changé cependant en Python 3 et à l'arrière-patché pour Python 2.7 donc un SyntaxError serait déclenché à la place. Cela a été documenté dans #question 27514:

Question n ° 27514: Faire d'avoir trop statique des blocs imbriqués une SyntaxError au lieu de SystemError.

La raison de ce changement dans les types d'exception a été donné par Serhiy Storchaka :

[...] SystemError n'est pas une exception doit être soulevée. SystemError est pour les erreurs qui ne peuvent pas être produits dans des conditions normales. Il ne doit être causé par une mauvaise utilisation de l'API C ou de piratage Python internes. Je pense que SyntaxError est plus appropriée dans ce cas [...].

22voto

coldspeed Points 111053

Cela a à voir avec l' blockstack, ce qui est une pile de l'octet code d'adresses, et est utilisé pour exécuter des blocs de code tels que les boucles et les exceptions.

Il arrive qu'une version de C (âgés de plus de C99) avait fixé cette limite à l' 20, et depuis le Disponible interprète est construit avec C, la même convention a été suivie:

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

La constante 20 semble être énoncées de la convention, et rien de plus.

[Liens de courtoisie Chrétienne Doyen.]


Pourquoi la limite est de 20?

Si l'argument de la convention n'est pas convaincante, alors jetez un oeil à La Zen de Python:

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

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

Comment pouvez-vous augmenter cette valeur?

Puisque cette valeur est une valeur codée en dur constante, le seul moyen de changer à l'effet dans vos programmes de reconstruction de la distribution python et exécuter votre script sur la construction de la nouvelle.

  1. Télécharger le disponible le code source de github

  2. Accédez cpython/Include/code.h

  3. Modifier la valeur de CO_MAXBLOCKS de quelque chose de plus grand que 20

  4. Recompiler Python (désactiver les tests, ils vont se plaindre)

3voto

Cary Shindell Points 1151

Voir la réponse ici: trop de statiquement les blocs imbriqués python Vous ne pouvez pas l'augmenter comme il est intégré à la syntaxe de python. La limite s'applique à tout type de code de la pile (pour les exceptions, les boucles, etc.) et la décision est prise par les concepteurs (sans doute pour éviter l'utilisation de la mémoire raisonnable). Une chose étrange est que ici: https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Include/code.h#L95 il est dit que 20 est le nombre maximum d'une fonction. Mais j'ai juste essayé de nidification 23 pour les boucles, pas à l'intérieur d'une fonction, et vous obtenez toujours l'erreur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X