4. Модель исполнения

4.1. Структура программы

Программа на Python состоит из блоков кода. block - это фрагмент текста программы на Python, который выполняется как единое целое. Ниже приведены блоки: модуль, тело функции и определение класса. Каждая команда, вводимая в интерактивном режиме, представляет собой блок. Файл сценария (файл, предоставляемый интерпретатору в качестве стандартного ввода или указанный в качестве аргумента командной строки интерпретатора) представляет собой блок кода. Команда сценария (команда, указанная в командной строке интерпретатора с параметром -c) представляет собой блок кода. Модуль, запускаемый как скрипт верхнего уровня (как модуль __main__) из командной строки с использованием аргумента -m, также является блоком кода. Строковый аргумент, передаваемый встроенным функциям eval() и exec(), представляет собой блок кода.

Блок кода выполняется в режиме execution frame. Фрейм содержит некоторую административную информацию (используемую для отладки) и определяет, где и как будет продолжено выполнение после завершения выполнения блока кода.

4.2. Присвоение имен и привязка

4.2.1. Привязка имен

Names относится к объектам. Имена вводятся с помощью операций привязки имен.

Следующие конструкции связывают имена:

  • формальные параметры для функций,

  • определения классов,

  • определения функций,

  • выражения присваивания,

  • targets, которые являются идентификаторами, если они встречаются в присваивании:

    • for заголовок цикла,

    • после as в операторе with, предложении except, предложении except* или в шаблоне as при сопоставлении структурных шаблонов,

    • в шаблоне захвата при сопоставлении структурных шаблонов

  • import заявления.

Оператор import вида from ... import * связывает все имена, определенные в импортируемом модуле, за исключением тех, которые начинаются со знака подчеркивания. Эта форма может использоваться только на уровне модуля.

Целевой объект, встречающийся в инструкции del, также считается привязанным для этой цели (хотя фактическая семантика заключается в том, чтобы отменить привязку имени).

Каждый оператор присваивания или импорта выполняется в блоке, определенном определением класса или функции, или на уровне модуля (блок кода верхнего уровня).

Если имя привязано к блоку, оно является локальной переменной этого блока, если только оно не объявлено как nonlocal или global. Если имя привязано на уровне модуля, это глобальная переменная. (Переменные блока кода модуля являются локальными и глобальными.) Если переменная используется в блоке кода, но не определена в нем, это free variable.

Каждое появление имени в тексте программы относится к binding этого имени, установленному следующими правилами разрешения имен.

4.2.2. Разрешение имен

scope определяет видимость имени внутри блока. Если в блоке определена локальная переменная, ее область действия включает этот блок. Если определение встречается в функциональном блоке, область действия распространяется на любые блоки, содержащиеся в определяющем, если только содержащийся в нем блок не вводит другую привязку для имени.

Когда в блоке кода используется имя, оно разрешается с использованием ближайшей охватывающей области. Совокупность всех таких областей, видимых для блока кода, называется environment блока.

Когда имя вообще не найдено, возникает исключение NameError. Если текущая область является областью функции, а имя ссылается на локальную переменную, которая еще не была привязана к значению в момент использования имени, возникает исключение UnboundLocalError. UnboundLocalError является подклассом NameError.

Если операция привязки имени выполняется в любом месте блока кода, все случаи использования имени в блоке рассматриваются как ссылки на текущий блок. Это может привести к ошибкам, если имя используется в блоке до его привязки. Это правило является тонким. В Python отсутствуют объявления, и операции привязки имен могут выполняться в любом месте внутри блока кода. Локальные переменные блока кода могут быть определены путем сканирования всего текста блока на предмет операций привязки имен. Примеры приведены в the FAQ entry on UnboundLocalError.

Если оператор global встречается внутри блока, все варианты использования имен, указанных в этом операторе, относятся к привязкам этих имен в пространстве имен верхнего уровня. Имена разрешаются в пространстве имен верхнего уровня путем поиска в глобальном пространстве имен, т.е. в пространстве имен модуля, содержащего блок кода, и в пространстве имен builtins, пространстве имен модуля builtins. Сначала выполняется поиск в глобальном пространстве имен. Если имена там не найдены, выполняется поиск в пространстве имен builtins. Оператор global должен предшествовать всем использованиям перечисленных имен.

Оператор global имеет ту же область действия, что и операция привязки имени, в том же блоке. Если ближайшая область действия для свободной переменной содержит глобальный оператор, свободная переменная рассматривается как глобальная.

Оператор nonlocal приводит к тому, что соответствующие имена ссылаются на ранее привязанные переменные в ближайшей области охватывающей функции. SyntaxError вызывается во время компиляции, если заданное имя не существует ни в одной области охватывающей функции.

Пространство имен для модуля создается автоматически при первом импорте модуля. Основной модуль для скрипта всегда называется __main__.

Блоки определения класса и аргументы для exec() и eval() являются особыми в контексте разрешения имен. Определение класса - это исполняемая инструкция, которая может использовать и определять имена. Эти ссылки соответствуют обычным правилам разрешения имен, за исключением того, что поиск несвязанных локальных переменных выполняется в глобальном пространстве имен. Пространство имен определения класса становится словарем атрибутов класса. Область имен, определенных в блоке class, ограничивается блоком class; это не распространяется на блоки кода методов - это включает в себя описания и генераторные выражения, поскольку они реализованы с использованием области действия функции. Это означает, что следующее не удастся выполнить:

class A:
    a = 42
    b = list(a + i for i in range(10))

4.2.3. Здания и ограниченное исполнение

Детали реализации CPython: Пользователи не должны касаться __builtins__; это строго относится к деталям реализации. Пользователи, желающие переопределить значения в пространстве имен builtins, должны import модуль builtins и соответствующим образом изменить его атрибуты.

Встроенное пространство имен, связанное с выполнением блока кода, на самом деле можно найти, выполнив поиск по имени __builtins__ в его глобальном пространстве имен; это должен быть словарь или модуль (в последнем случае используется словарь модуля). По умолчанию, когда в модуле __main__, __builtins__ является встроенным модулем builtins; когда в любом другом модуле, __builtins__ является псевдонимом для словаря builtins сам модуль.

4.2.4. Взаимодействие с динамическими функциями

Определение имен свободных переменных происходит во время выполнения, а не во время компиляции. Это означает, что следующий код выведет 42:

i = 10
def f():
    print(i)
i = 42
f()

Функции eval() и exec() не имеют доступа к полной среде для разрешения имен. Имена могут быть разрешены в локальном и глобальном пространствах имен вызывающего объекта. Свободные переменные разрешаются не в ближайшем окружающем пространстве имен, а в глобальном пространстве имен. [1] Функции exec() и eval() имеют необязательные аргументы для переопределения глобального и локального пространства имен. Если указано только одно пространство имен, оно используется для обоих.

4.3. Исключения

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

Интерпретатор Python генерирует исключение при обнаружении ошибки во время выполнения (например, при делении на ноль). Программа на Python также может явно генерировать исключение с помощью инструкции raise. Обработчики исключений задаются с помощью инструкции tryexcept. Предложение finally такого оператора может быть использовано для указания кода очистки, который не обрабатывает исключение, но выполняется независимо от того, возникло исключение в предыдущем коде или нет.

Python использует «завершающую» модель обработки ошибок: обработчик исключений может выяснить, что произошло, и продолжить выполнение на внешнем уровне, но он не может устранить причину ошибки и повторить неудачную операцию (за исключением повторного ввода вызывающего ошибку фрагмента кода сверху).

Когда исключение вообще не обрабатывается, интерпретатор завершает выполнение программы или возвращается к своему интерактивному основному циклу. В любом случае он выводит обратную трассировку стека, за исключением случаев, когда исключение равно SystemExit.

Исключения определяются экземплярами класса. Предложение except выбирается в зависимости от класса экземпляра: оно должно ссылаться на класс экземпляра или на его non-virtual base class. Экземпляр может быть получен обработчиком и может содержать дополнительную информацию об исключительном состоянии.

Примечание

Сообщения об исключениях не являются частью API Python. Их содержимое может меняться от одной версии Python к другой без предупреждения, и на них не следует полагаться в коде, который будет выполняться в нескольких версиях интерпретатора.

Смотрите также описание инструкции try в разделе Оператор try и инструкции raise в разделе Оператор raise.

Сноски

Вернуться на верх