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

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

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

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

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

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

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

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

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

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

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

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

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

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

    • после as в операторе with, предложении except или в as-pattern при структурном сопоставлении шаблонов,

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

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

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

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

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

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

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

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

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

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

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

Если операция связывания имени происходит в любом месте блока кода, все использования имени в блоке рассматриваются как ссылки на текущий блок. Это может привести к ошибкам, когда имя используется внутри блока до его связывания. Это правило является тонким. В Python нет деклараций, и операции связывания имен могут происходить в любом месте блока кода. Локальные переменные блока кода могут быть определены путем сканирования всего текста блока на предмет операций связывания имен.

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

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

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

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

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

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

4.2.3. Встроенные модули и ограниченное выполнение

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

Пространство имен 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.

Сноски

1

Это ограничение возникает потому, что код, выполняемый этими операциями, недоступен на момент компиляции модуля.

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