7. Простые высказывания

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

simple_stmt ::=  expression_stmt
                 | assert_stmt
                 | assignment_stmt
                 | augmented_assignment_stmt
                 | annotated_assignment_stmt
                 | pass_stmt
                 | del_stmt
                 | return_stmt
                 | yield_stmt
                 | raise_stmt
                 | break_stmt
                 | continue_stmt
                 | import_stmt
                 | future_stmt
                 | global_stmt
                 | nonlocal_stmt
                 | type_stmt

7.1. Выражения

Операторы выражения используются (в основном в интерактивном режиме) для вычисления и записи значения или (обычно) для вызова процедуры (функции, которая не возвращает значимого результата; в Python процедуры возвращают значение None). Другие варианты использования операторов выражения допустимы и иногда полезны. Синтаксис оператора выражения следующий:

expression_stmt ::=  starred_expression

Оператор выражения оценивает список выражений (который может быть одним выражением).

В интерактивном режиме, если значение не None, оно преобразуется в строку с помощью встроенной функции repr(), и полученная строка записывается в стандартный вывод в отдельной строке (за исключением случаев, когда результат равен None, так что вызовы процедур не приводят к выводу).

7.2. Ведомости заданий

Операторы присваивания используются для (повторной) привязки имен к значениям и для изменения атрибутов или элементов изменяемых объектов:

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target

(Определения синтаксиса для attributeref, subscription и slicing см. в разделе Праймериз).

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

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

Назначение объекта целевому списку, по желанию заключенному в круглые или квадратные скобки, рекурсивно определяется следующим образом.

  • Если список целей состоит из одной цели без запятой в конце и, по желанию, в круглых скобках, то объект назначается этой цели.

  • Эльза:

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

    • Иначе: Объект должен быть итерируемым с тем же количеством элементов, что и целей в списке целей, и элементы назначаются слева направо на соответствующие цели.

Назначение объекта одной цели рекурсивно определяется следующим образом.

  • Если целью является идентификатор (имя):

    • Если имя не встречается в операторе global или nonlocal в текущем блоке кода: имя привязывается к объекту в текущем локальном пространстве имен.

    • Иначе: имя привязывается к объекту в глобальном пространстве имен или внешнем пространстве имен, определяемом nonlocal, соответственно.

    Имя отбрасывается, если оно уже было привязано. Это может привести к тому, что счетчик ссылок на объект, ранее связанный с именем, достигнет нуля, что приведет к деаллокации объекта и вызову его деструктора (если он есть).

  • Если целью является ссылка на атрибут: Оценивается первичное выражение в ссылке. В результате должен появиться объект с присваиваемыми атрибутами; если это не так, вызывается сообщение TypeError. Затем этот объект просят присвоить назначенный объект заданному атрибуту; если он не может выполнить присвоение, то возникает исключение (обычно, но не обязательно AttributeError).

    Примечание: Если объект является экземпляром класса и ссылка на атрибут встречается с обеих сторон оператора присваивания, то выражение в правой части a.x может обращаться либо к атрибуту экземпляра, либо (если атрибут экземпляра не существует) к атрибуту класса. Левостороннее выражение a.x всегда устанавливается как атрибут экземпляра, создавая его при необходимости. Таким образом, два вхождения a.x не обязательно относятся к одному и тому же атрибуту: если выражение правой части обращается к атрибуту класса, то левая часть создает новый атрибут экземпляра в качестве цели присваивания:

    class Cls:
        x = 3             # class variable
    inst = Cls()
    inst.x = inst.x + 1   # writes inst.x as 4 leaving Cls.x as 3
    

    Это описание не обязательно относится к атрибутам дескрипторов, таким как свойства, созданные с помощью property().

  • Если целью является подписка: Оценивается первичное выражение в ссылке. Оно должно дать либо объект последовательности с возможностью изменения (например, список), либо объект отображения (например, словарь). Затем оценивается выражение подписки.

    Если первичным является объект последовательности с возможностью изменения (например, список), то подстрочный индекс должен быть целым числом. Если он отрицательный, к нему прибавляется длина последовательности. Полученное значение должно быть неотрицательным целым числом, меньшим длины последовательности, и последовательности предлагается присвоить назначенный объект своему элементу с этим индексом. Если индекс выходит за пределы диапазона, выдается значение IndexError (присваивание последовательности с подписями не может добавлять новые элементы в список).

    Если первичным является объект отображения (например, словарь), то подскрипт должен иметь тип, совместимый с типом ключа отображения, а затем отображению предлагается создать пару ключ/значение, которая сопоставляет подскрипт с назначенным объектом. Это может быть либо замена существующей пары ключ/значение с тем же значением ключа, либо вставка новой пары ключ/значение (если ключ с тем же значением не существовал).

    Для объектов, определяемых пользователем, вызывается метод __setitem__() с соответствующими аргументами.

  • Если цель является срезом: Оценивается первичное выражение в ссылке. Оно должно давать изменяемый объект последовательности (например, список). Присваиваемый объект должен быть объектом последовательности того же типа. Затем оцениваются выражения нижней и верхней границ, если они присутствуют; по умолчанию это ноль и длина последовательности. Границы должны оцениваться как целые числа. Если одна из границ отрицательна, к ней прибавляется длина последовательности. Полученные границы обрезаются, чтобы лежать между нулем и длиной последовательности, включительно. Наконец, объекту последовательности предлагается заменить фрагмент элементами назначенной последовательности. Длина фрагмента может отличаться от длины назначенной последовательности, тем самым изменяя длину целевой последовательности, если целевая последовательность это допускает.

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

Хотя определение присваивания подразумевает, что пересечения между левой и правой сторонами являются «одновременными» (например, a, b = b, a меняет местами две переменные), пересечения внутри коллекции присваиваемых переменных происходят слева направо, что иногда приводит к путанице. Например, следующая программа печатает [0, 2]:

x = [0, 1]
i = 0
i, x[i] = 1, 2         # i is updated, then x[i] is updated
print(x)

См.также

PEP 3132 - Расширенная распаковка итераций

Спецификация для функции *target.

7.2.1. Расширенные операторы присваивания

Дополненное присваивание - это сочетание в одном операторе бинарной операции и оператора присваивания:

augmented_assignment_stmt ::=  augtarget augop (expression_list | yield_expression)
augtarget                 ::=  identifier | attributeref | subscription | slicing
augop                     ::=  "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
                               | ">>=" | "<<=" | "&=" | "^=" | "|="

(Синтаксические определения последних трех символов см. в разделе Праймериз).

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

Расширенное выражение присваивания x += 1 можно переписать как x = x + 1, чтобы добиться аналогичного, но не совсем одинакового эффекта. В дополненной версии x оценивается только один раз. Также, когда это возможно, фактическая операция выполняется вместе, то есть вместо создания нового объекта и присвоения его целевому объекту, старый объект модифицируется.

В отличие от обычных присваиваний, дополненные присваивания оценивают левую часть перед оценкой правой части. Например, a[i] += f(x) сначала просматривает a[i], затем оценивает f(x) и выполняет сложение, и, наконец, записывает результат обратно в a[i].

За исключением присваивания кортежам и нескольким целям в одном операторе, присваивание, выполняемое операторами дополненного присваивания, обрабатывается так же, как и обычное присваивание. Аналогично, за исключением возможного поведения in-place, бинарные операции, выполняемые дополненным присваиванием, не отличаются от обычных бинарных операций.

Для целей, которые являются ссылками на атрибуты, применяется тот же caveat about class and instance attributes, что и для обычных назначений.

7.2.2. Аннотированные задания

Назначение Annotation - это сочетание в одном операторе аннотации переменной или атрибута и необязательного оператора назначения:

annotated_assignment_stmt ::=  augtarget ":" expression
                               ["=" (starred_expression | yield_expression)]

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

Для простых имен как целей присваивания, если они находятся в области видимости класса или модуля, аннотации оцениваются и хранятся в специальном атрибуте класса или модуля __annotations__, который представляет собой словарное отображение имен переменных (искаженных, если они приватные) на оцененные аннотации. Этот атрибут доступен для записи и автоматически создается в начале выполнения тела класса или модуля, если аннотации найдены статически.

Для выражений, являющихся целями присваивания, аннотации оцениваются, если они находятся в области видимости класса или модуля, но не сохраняются.

Если имя аннотировано в области видимости функции, то это имя является локальным для этой области видимости. Аннотации никогда не оцениваются и не хранятся в областях видимости функций.

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

См.также

PEP 526 - Синтаксис для аннотаций переменных

Предложение, добавляющее синтаксис для аннотирования типов переменных (включая переменные класса и переменные экземпляра), вместо того, чтобы выражать их через комментарии.

PEP 484 - Подсказки типа

Предложение, добавляющее модуль typing для обеспечения стандартного синтаксиса для аннотаций типов, который может использоваться в инструментах статического анализа и IDE.

Изменено в версии 3.8: Теперь аннотированные присваивания позволяют использовать в правой части те же выражения, что и обычные присваивания. Ранее некоторые выражения (например, непарные кортежные выражения) вызывали синтаксическую ошибку.

7.3. Заявление assert

Операторы Assert - это удобный способ вставки отладочных утверждений в программу:

assert_stmt ::=  "assert" expression ["," expression]

Простая форма, assert expression, эквивалентна

if __debug__:
    if not expression: raise AssertionError

Расширенная форма, assert expression1, expression2, эквивалентна

if __debug__:
    if not expression1: raise AssertionError(expression2)

Эти эквивалентности предполагают, что __debug__ и AssertionError ссылаются на встроенные переменные с такими именами. В текущей реализации встроенная переменная __debug__ - это True в обычных условиях, False - когда запрашивается оптимизация (опция командной строки -O). Текущий генератор кода не выдает код для оператора assert, когда оптимизация запрашивается во время компиляции. Обратите внимание, что в сообщение об ошибке нет необходимости включать исходный код выражения, которое завершилось неудачей; он будет отображен как часть трассировки стека.

Присвоение значения __debug__ недопустимо. Значение встроенной переменной определяется при запуске интерпретатора.

7.4. Заявление pass

pass_stmt ::=  "pass"

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

def f(arg): pass    # a function that does nothing (yet)

class C: pass       # a class with no methods (yet)

7.5. Заявление del

del_stmt ::=  "del" target_list

Удаление определяется рекурсивно, подобно тому, как определяется присваивание. Вместо того чтобы описывать это во всех подробностях, приведем несколько подсказок.

При удалении списка целей рекурсивно удаляется каждая цель, слева направо.

Удаление имени удаляет привязку этого имени из локального или глобального пространства имен, в зависимости от того, встречается ли это имя в операторе global в том же блоке кода. Если имя не связано, будет вызвано исключение NameError.

Удаление ссылок на атрибуты, подписок и срезов передается первичному объекту; удаление среза в общем случае эквивалентно присвоению пустого среза нужного типа (но даже это определяется срезовым объектом).

Изменено в версии 3.2: Ранее удаление имени из локального пространства имен, если оно встречается в качестве свободной переменной во вложенном блоке, было незаконным.

7.6. Заявление return

return_stmt ::=  "return" [expression_list]

return может встречаться только синтаксически вложенным в определение функции, но не внутри вложенного определения класса.

Если присутствует список выражений, то он оценивается, иначе подставляется None.

return оставляет текущий вызов функции со списком выражений (или None) в качестве возвращаемого значения.

Когда return передает управление из оператора try с предложением finally, это предложение finally выполняется до выхода из функции.

В функции-генераторе оператор return указывает на то, что генератор завершен и приведет к появлению StopIteration. Возвращенное значение (если оно есть) используется в качестве аргумента для построения StopIteration и становится атрибутом StopIteration.value.

В функции асинхронного генератора пустое утверждение return указывает на то, что асинхронный генератор завершен, и приводит к появлению сообщения StopAsyncIteration. Непустой оператор return является синтаксической ошибкой в функции асинхронного генератора.

7.7. Заявление yield

yield_stmt ::=  yield_expression

Выражение yield семантически эквивалентно выражению yield expression. Оператор yield можно использовать, чтобы опустить круглые скобки, которые в противном случае потребовались бы в эквивалентном выражении yield. Например, оператор yield

yield <expr>
yield from <expr>

эквивалентны операторам выражения yield

(yield <expr>)
(yield from <expr>)

Выражения и утверждения yield используются только при определении функции generator и только в теле функции-генератора. Использование yield в определении функции достаточно для того, чтобы это определение создало функцию-генератор вместо обычной функции.

Для получения подробной информации о семантике yield обратитесь к разделу Выражения доходности.

7.8. Заявление raise

raise_stmt ::=  "raise" [expression ["from" expression]]

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

В противном случае raise оценивает первое выражение как объект исключения. Он должен быть либо подклассом, либо экземпляром BaseException. Если это класс, то экземпляр исключения будет получен при необходимости путем инстанцирования класса без аргументов.

type исключения - это класс экземпляра исключения, value - сам экземпляр.

Объект traceback обычно создается автоматически при возникновении исключения и присоединяется к нему в качестве атрибута __traceback__. Вы можете создать исключение и установить свой собственный traceback за один шаг, используя метод with_traceback() exception (который возвращает тот же экземпляр исключения, а traceback устанавливается в его аргумент), например, так:

raise Exception("foo occurred").with_traceback(tracebackobj)

Клаузула from используется для цепочки исключений: если она задана, второе выражение должно быть другим классом или экземпляром исключения. Если второе выражение является экземпляром исключения, оно будет присоединено к поднятому исключению в качестве атрибута __cause__ (который доступен для записи). Если выражение является классом исключения, то этот класс будет инстанцирован, а полученный экземпляр исключения будет присоединен к поднятому исключению в качестве атрибута __cause__. Если поднятое исключение не будет обработано, будут выведены оба исключения:

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
    print(1 / 0)
          ~~^~~
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
    raise RuntimeError("Something bad happened") from exc
RuntimeError: Something bad happened

Аналогичный механизм неявно работает, если новое исключение возникает, когда исключение уже обрабатывается. Исключение может быть обработано при использовании клаузулы except или finally, или оператора with. При этом предыдущее исключение присоединяется в качестве атрибута __context__ нового исключения:

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
    print(1 / 0)
          ~~^~~
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
    raise RuntimeError("Something bad happened")
RuntimeError: Something bad happened

Цепочку исключений можно явно запретить, указав None в предложении from:

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened") from None
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

Дополнительную информацию об исключениях можно найти в разделе Исключения, а информацию об обработке исключений - в разделе Заявление try.

Изменено в версии 3.3: None теперь разрешен как Y в raise X from Y.

Добавлен атрибут __suppress_context__ для запрета автоматического отображения контекста исключений.

Изменено в версии 3.11: Если отслеживание активного исключения изменено в предложении except, последующий оператор raise повторно вызывает исключение с измененным отслежением. Ранее исключение повторно вызывалось с трассировкой, которая была в момент его поимки.

7.9. Заявление break

break_stmt ::=  "break"

Синтаксически break может встречаться только вложенным в цикл for или while, но не вложенным в определение функции или класса внутри этого цикла.

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

Если цикл for завершается нажатием break, цель управления циклом сохраняет свое текущее значение.

Когда break передает управление из оператора try с предложением finally, это предложение finally выполняется до выхода из цикла.

7.10. Заявление continue

continue_stmt ::=  "continue"

Синтаксически continue может встречаться только вложенным в цикл for или while, но не вложенным в определение функции или класса внутри этого цикла. Он продолжается в следующем цикле ближайшего охватывающего цикла.

Когда continue передает управление из оператора try с предложением finally, это предложение finally выполняется перед тем, как действительно начать следующий цикл.

7.11. Заявление import

import_stmt     ::=  "import" module ["as" identifier] ("," module ["as" identifier])*
                     | "from" relative_module "import" identifier ["as" identifier]
                     ("," identifier ["as" identifier])*
                     | "from" relative_module "import" "(" identifier ["as" identifier]
                     ("," identifier ["as" identifier])* [","] ")"
                     | "from" relative_module "import" "*"
module          ::=  (identifier ".")* identifier
relative_module ::=  "."* module | "."+

Основной оператор импорта (без предложения from) выполняется в два этапа:

  1. найти модуль, при необходимости загрузить и инициализировать его

  2. определить имя или имена в локальном пространстве имен для области видимости, в которой встречается оператор import.

Если оператор содержит несколько пунктов (разделенных запятыми), эти два шага выполняются отдельно для каждого пункта, как если бы пункты были разделены на отдельные операторы импорта.

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

Если запрашиваемый модуль успешно найден, он будет доступен в локальном пространстве имен одним из трех способов:

  • Если за именем модуля следует as, то имя, следующее за as, привязывается непосредственно к импортируемому модулю.

  • Если другое имя не указано, а импортируемый модуль является модулем верхнего уровня, то его имя связывается в локальном пространстве имен как ссылка на импортируемый модуль

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

В форме from используется несколько более сложный процесс:

  1. найти модуль, указанный в предложении from, при необходимости загрузив и инициализировав его;

  2. для каждого из идентификаторов, указанных в пунктах import:

    1. проверить, есть ли в импортируемом модуле атрибут с таким именем

    2. если нет, попытайтесь импортировать подмодуль с таким именем, а затем снова проверьте импортированный модуль на наличие этого атрибута

    3. если атрибут не найден, то будет выведен ImportError.

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

Примеры:

import foo                 # foo imported and bound locally
import foo.bar.baz         # foo, foo.bar, and foo.bar.baz imported, foo bound locally
import foo.bar.baz as fbb  # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as fbb
from foo.bar import baz    # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as baz
from foo import attr       # foo imported and foo.attr bound as attr

Если список идентификаторов заменен звездочкой ('*'), то все публичные имена, определенные в модуле, привязываются к локальному пространству имен для области видимости, в которой встречается оператор import.

Публичные имена, определенные модулем, определяются путем проверки пространства имен модуля на наличие переменной с именем __all__; если она определена, то должна представлять собой последовательность строк, которые являются именами, определенными или импортированными этим модулем. Имена, указанные в __all__, считаются общедоступными и должны существовать. Если __all__ не определен, то набор публичных имен включает все имена, находящиеся в пространстве имен модуля, которые не начинаются с символа подчеркивания ('_'). __all__ должен содержать весь общедоступный API. Это сделано для того, чтобы избежать случайного экспорта элементов, не являющихся частью API (например, библиотечных модулей, которые были импортированы и использованы внутри модуля).

Дикая форма импорта — from module import * — разрешена только на уровне модуля. Попытка использовать ее в определениях классов или функций вызовет ошибку SyntaxError.

При указании модуля для импорта не обязательно указывать абсолютное имя модуля. Когда модуль или пакет содержится в другом пакете, можно сделать относительный импорт в пределах того же верхнего пакета без необходимости упоминания имени пакета. Используя ведущие точки в указанном модуле или пакете после from, вы можете указать, как высоко подняться по иерархии текущих пакетов, не указывая точных имен. Одна ведущая точка означает текущий пакет, в котором существует модуль, выполняющий импорт. Две точки означают переход на один уровень пакета. Три точки - на два уровня вверх и т. д. Таким образом, если вы выполните from . import mod из модуля в пакете pkg, то в итоге импортируете pkg.mod. Если вы выполните from ..subpkg2 import mod из пакета pkg.subpkg1, вы импортируете pkg.subpkg2.mod. Спецификация относительного импорта содержится в разделе Относительный импорт пакетов.

importlib.import_module() предоставляется для поддержки приложений, которые динамически определяют загружаемые модули.

Поднимает auditing event import с аргументами module, filename, sys.path, sys.meta_path, sys.path_hooks.

7.11.1. Будущие заявления

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

Утверждение future предназначено для облегчения перехода на будущие версии Python, которые вносят несовместимые изменения в язык. Оно позволяет использовать новые возможности на основе отдельных модулей до выпуска, в котором эти возможности станут стандартными.

future_stmt ::=  "from" "__future__" "import" feature ["as" identifier]
                 ("," feature ["as" identifier])*
                 | "from" "__future__" "import" "(" feature ["as" identifier]
                 ("," feature ["as" identifier])* [","] ")"
feature     ::=  identifier

Будущее утверждение должно находиться в верхней части модуля. Единственными строками, которые могут появиться перед будущим утверждением, являются:

  • docstring модуля (если есть),

  • комментарии,

  • пустые строки и

  • другие будущие заявления.

Единственная функция, которая требует использования оператора future, - это annotations (см. PEP 563).

Все исторические функции, включенные в утверждение будущего, по-прежнему распознаются Python 3. В список входят absolute_import, division, generators, generator_stop, unicode_literals, print_function, nested_scopes и with_statement. Все они избыточны, поскольку всегда включены, и сохраняются только для обратной совместимости.

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

Для любого выпуска компилятор знает, какие имена функций были определены, и выдает ошибку во время компиляции, если оператор future содержит неизвестную ему функцию.

Семантика прямого выполнения такая же, как и для любого оператора import: существует стандартный модуль __future__, описанный позже, и он будет импортирован обычным образом в момент выполнения оператора future.

Интересная семантика во время выполнения зависит от конкретной возможности, которую обеспечивает утверждение future.

Обратите внимание, что в утверждении: нет ничего особенного:

import __future__ [as name]

Это не оператор будущего; это обычный оператор импорта, не имеющий специальной семантики или синтаксических ограничений.

Код, скомпилированный с помощью вызовов встроенных функций exec() и compile(), которые происходят в модуле M, содержащем будущее утверждение, по умолчанию будет использовать новый синтаксис или семантику, связанную с будущим утверждением. Этим можно управлять с помощью необязательных аргументов в compile(). — подробности см. в документации к этой функции.

Утверждение future, набранное в приглашении интерактивного интерпретатора, будет действовать до конца сеанса интерпретатора. Если интерпретатор запущен с опцией -i, ему передано имя сценария для выполнения, и сценарий содержит утверждение future, оно будет действовать в интерактивной сессии, запущенной после выполнения сценария.

См.также

PEP 236 - Назад в __будущее_

Оригинальное предложение для механизма __future__.

7.12. Заявление global

global_stmt ::=  "global" identifier ("," identifier)*

Утверждение global - это объявление, которое сохраняется для всего текущего блока кода. Оно означает, что перечисленные идентификаторы должны интерпретироваться как глобальные. Без global присвоение глобальной переменной невозможно, хотя свободные переменные могут ссылаться на глобальные, не будучи объявленными глобальными.

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

Имена, перечисленные в операторе global, не должны быть определены как формальные параметры, или как цели в операторах with или предложениях except, или в списке целей for, определении class, определении функции, операторе import, или аннотации переменных.

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

Примечание программиста: global - это директива для парсера. Она применяется только к коду, разобранному одновременно с оператором global. В частности, оператор global, содержащийся в строке или объекте кода, переданном встроенной функции exec(), не влияет на блок кода, содержащий вызов функции, и код, содержащийся в такой строке, не подвержен влиянию операторов global в коде, содержащем вызов функции. То же самое относится к функциям eval() и compile().

7.13. Заявление nonlocal

nonlocal_stmt ::=  "nonlocal" identifier ("," identifier)*

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

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

См.также

PEP 3104 - Доступ к именам во внешних областях

Спецификация для оператора nonlocal.

Примечание программиста: nonlocal является директивой парсеру и применяется только к коду, разобранному вместе с ним. См. примечание для оператора global.

7.14. Заявление type

type_stmt ::=  'type' identifier [type_params] "=" expression

Оператор type объявляет псевдоним типа, который является экземпляром typing.TypeAliasType.

Например, следующий оператор создает псевдоним типа:

type Point = tuple[float, float]

Этот код примерно эквивалентен:

annotation-def VALUE_OF_Point():
    return tuple[float, float]
Point = typing.TypeAliasType("Point", VALUE_OF_Point())

annotation-def обозначает annotation scope, которая ведет себя в основном как функция, но с несколькими небольшими отличиями.

Значение псевдонима типа оценивается в области видимости аннотации. Оно не оценивается при создании псевдонима типа, а только при обращении к значению через атрибут __value__ псевдонима типа (см. Ленивая оценка). Это позволяет псевдониму типа ссылаться на имена, которые еще не определены.

Псевдонимы типов можно сделать общими, добавив type parameter list после имени. Подробнее см. в разделе Псевдонимы общих типов.

type является soft keyword.

Added in version 3.12.

См.также

PEP 695 - Тип Синтаксис параметра

Введены оператор type и синтаксис для общих классов и функций.