Почему Python имеет ограничение на количество статических блоков, которые могут быть вложены?

количество статически вложенных блоков в Python ограничено 20. То есть, вложения 19 for петли будут в порядке (хотя чрезмерно много времени;O(n^19) безумно), но вложенность 20 потерпит неудачу с:

SyntaxError: too many statically nested blocks

какова основная причина наличия такого предела? Есть ли способ увеличить лимит?

3 ответов


это ограничение относится не только к for петли, но и для всех других блоков потока управления. Ограничение количества вложенных блоков потока управления определяется внутри код.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 */

наиболее вероятной причиной этого ограничения является сохранение использования памяти на разумном уровне при выполнении вложенных блоков. Вероятно, это похоже на ограничение Python накладывает на рекурсивные вызовы. Это ограничение можно увидеть вкомпиляции.c:

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

более конкретный ответ о том, почему Python имеет этот специальный предел и почему они не могут избавиться от него, был дан Майкл Хадсон в 2004 письмо списка рассылки Python:

место на. Это связано с "blockstack", очень внутренним подробно о реализации Python. Мы хотели бы избавиться от него (не потому что мы хотим, чтобы люди напишите код с более чем 20 вложенных петли :-) но это не особенно легко (наконец-то: блоки наибольшая проблема.)

обратите внимание, что в Python 2.6 и ниже, нарушая максимальное количество вложенных циклов вызвал бы SystemError не SyntaxError. Однако это было изменено в Python 3 и обратно исправлено на Python 2.7, поэтому SyntaxError вместо этого будет поднят. Это было задокументировано в выпуск#27514:

проблема #27514: сделайте слишком много статически вложенных блоков SyntaxError вместо SystemError.

причина этого изменения в типах исключений была указана Сергей Университета :

[...] SystemError не является исключением, которое должно быть вызвано. SystemError предназначен для ошибок, которые не могут возникнуть в обычном случае. Это должно быть вызвано только неправильным использованием C API или взломом Python internals. Я думаю, что SyntaxError более подходит в этом случае [...].


это имеет отношение к blockstack, который является стеком адресов байтового кода и используется для выполнения блоков кода, таких как циклы и исключения.

так получилось, что версия C (старше C99) установила этот предел в 20, и поскольку интерпретатор CPython построен с помощью C,та же Конвенция была соблюдена:

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

постоянной 20 кажется, установлен из конвенции, и ничего больше.

[ссылки любезно предоставлены Christian Dean.]


почему предел 20?

если аргумент конвенции не убедителен, то взгляните на Дзен питона:

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

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

как вы можете увеличить это значение?

поскольку это значение является жестко закодированной константой, единственный способ изменить его в ваших программах-перестроить дистрибутив python и запустить скрипт в новой сборке.

  1. загрузите исходный код cpython из github

  2. перейти к cpython/Include/code.h

  3. изменить значение CO_MAXBLOCKS к чему-нибудь большему, чем 20

  4. перекомпилировать Python (отключить тесты,они будут жаловаться)


см. ответ здесь: слишком много статически вложенных блоков python Вы не можете увеличить его, поскольку он встроен в синтаксис python. Ограничение относится к любому виду стек код (исключения, петли и т. д.) и является решением дизайнеров (предположительно, чтобы сохранить разумное использование памяти). Одна странная вещь здесь: https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Include/code.h#L95 он говорит, что 20-это максимальное число в a функция. Но я только что попробовал вложить 23 для циклов, а не внутри функции, и вы все равно получите ошибку.