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

7.1. Выражения-операторы

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

expression_stmt ::=  starred_expression

Оператор 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().

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

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

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

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

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

Детали реализации 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].

За исключением присвоения кортежам и нескольким целевым объектам в одном операторе, назначение, выполняемое дополненными операторами присваивания, обрабатывается так же, как и обычные назначения. Аналогично, за исключением возможного поведения «на месте», двоичная операция, выполняемая с помощью расширенного присваивания, ничем не отличается от обычных двоичных операций.

Для целевых объектов, которые являются ссылками на атрибуты, применяется тот же 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__. Вы можете создать исключение и задать свою собственную обратную трассировку за один шаг, используя метод with_traceback() exception (который возвращает тот же экземпляр исключения, с параметром обратной трассировки, равным его аргументу), например:

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

Оператор future должен отображаться в верхней части модуля. Перед оператором future могут отображаться только следующие строки:

  • строка документации модуля (если таковая имеется),

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

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

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

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

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

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

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

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

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

Обратите внимание, что в этом заявлении нет ничего особенного:

import __future__ [as name]

Это не оператор future; это обычный оператор import без каких-либо особых семантических или синтаксических ограничений.

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

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

См.также

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

Первоначальное предложение по __будущему__ механизму.

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 приводит к тому, что перечисленные идентификаторы ссылаются на ранее привязанные переменные в ближайшей охватывающей области, за исключением глобальных. Это важно, поскольку по умолчанию для привязки сначала выполняется поиск в локальном пространстве имен. Оператор позволяет инкапсулированному коду повторно связывать переменные за пределами локальной области видимости, помимо глобальной (модульной) области видимости.

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

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

См.также

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

Спецификация для инструкции nonlocal.

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