Простые операторы
Простой оператор состоит из одной логической строки. Несколько простых операторов могут находиться в одной строке, разделенные точкой с запятой. Синтаксис простых операторов:
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. Операторы выражений
Операторы выражений используются (в основном в интерактивном режиме) для вычисления и записи значения или (обычно) для вызова процедуры (функции, не возвращающей осмысленного результата; в 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
(См. раздел Основные выражения для определения синтаксиса ссылки на атрибут, индексации и срезов.)
Оператор присваивания вычисляет список выражений (помните, что это может быть одиночное выражение или список выражений, разделенных запятыми, что даёт кортеж) и присваивает единственный полученный объект каждому из списков мишеней слева направо.
Присваивание определяется рекурсивно в зависимости от формы списка мишеней. Когда мишень является частью изменяемого объекта (ссылка на атрибут, индексация или срез), изменяемый объект должен в конечном итоге выполнить присваивание и решить о его корректности, и может вызвать исключение, если присваивание неприемлемо. Правила, соблюдаемые различными типами, и возбуждаемые исключения приводятся с определением типов объектов (см. раздел Стандартная иерархия типов).
Присваивание объекта списку мишеней, необязательно заключённому в круглые или квадратные скобки, определяется рекурсивно следующим образом.
- Если список мишеней содержит одну мишень без конечной запятой, необязательно в круглых скобках, объект присваивается этой мишени.
-
В противном случае:
- Если список мишеней содержит одну мишень с префиксом звёздочкой, называемой «звёздчатой» мишенью: объект должен быть итерируемым с как минимум таким же количеством элементов, как мишеней в списке мишеней минус одна. Первые элементы итерируемого объекта присваиваются мишеням перед звёздчатой мишенью слева направо. Последние элементы итерируемого объекта присваиваются мишеням после звёздчатой мишени. Список оставшихся элементов в итерируемом объекте затем присваивается звёздчатой мишени (список может быть пустым).
- В противном случае: объект должен быть итерируемым с таким же количеством элементов, как мишеней в списке мишеней, и элементы присваиваются мишеням слева направо, соответствующим мишеням.
Присваивание объекта одной мишени определяется рекурсивно следующим образом.
-
Если мишенью является идентификатор (имя):
- Если имя не встречается в операторе
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].
За исключением присваивания кортежам и нескольким мишеням в одном операторе, присваивание, выполняемое операторами расширенного присваивания, обрабатывается так же, как и обычные присваивания. Аналогично, за исключением возможного поведения на месте, бинарная операция, выполняемая операторами расширенного присваивания, такая же, как и обычные бинарные операции.
Для мишеней, являющихся ссылками на атрибуты, применима та же оговорка о классах и атрибутах экземпляров, что и для обычных присваиваний.
7.2.2. Аннотированные операторы присваивания
Аннотация присваивания — это комбинация аннотации переменной или атрибута и необязательного оператора присваивания в одном операторе:
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-выражение. Оператор yield можно использовать для опускания скобок, которые в противном случае потребовались бы в эквивалентном операторе yield-выражения. Например, операторы yield
yield <expr> yield from <expr>
эквивалентны yield-выражениям
(yield <expr>) (yield from <expr>)
Yield-выражения и операторы используются только при определении функции-генератора и только в теле функции-генератора. Использование yield в определении функции достаточно для того, чтобы это определение создавало функцию-генератор вместо обычной функции.
Для получения подробной информации о семантике yield см. раздел Yield-выражения.
7.8. Оператор raise
raise_stmt ::= "raise" [expression ["from" expression]]
Если выражений нет, raise повторно поднимает исключение, которое в данный момент обрабатывается, что также известно как активное исключение. Если в данный момент активного исключения нет, возникает исключение RuntimeError, указывающее на ошибку.
В противном случае, raise вычисляет первое выражение как объект исключения. Он должен быть подклассом или экземпляром BaseException. Если это класс, экземпляр исключения будет получен при необходимости путем создания экземпляра класса без аргументов.
Тип исключения — это класс экземпляра исключения, а значение — сам экземпляр.
Объект отслеживания ошибки обычно создаётся автоматически при возникновении исключения и прикрепляется к нему в качестве атрибута __traceback__, который можно изменить. Вы можете создать исключение и установить свой собственный отслеживающий объект в одном шаге, используя метод исключения with_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>
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>
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>
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
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.
Новое в версии 3.3: Атрибут __suppress_context__ для подавления автоматического отображения контекста исключения.
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 части) выполняется в два этапа:
- найти модуль, загрузить и инициализировать его при необходимости
- определить имя или имена в локальном пространстве имён для области, в которой находится оператор
import.
Когда оператор содержит несколько частей (разделенных запятыми), два этапа выполняются отдельно для каждой части, как если бы части были разделены в отдельные операторы импорта.
Подробности первого этапа, поиска и загрузки модулей, описаны более подробно в разделе о системе импорта, который также описывает различные типы пакетов и модулей, которые могут быть импортированы, а также все хуки, которые могут использоваться для настройки системы импорта. Обратите внимание, что ошибки на этом этапе могут указывать либо на то, что модуль не был найден, либо на то, что произошла ошибка при инициализации модуля, которая включает выполнение кода модуля.
Если запрашиваемый модуль успешно получен, он будет доступен в локальном пространстве имен одним из трех способов:
- Если имя модуля следует за
as, то имя, следующее заas, напрямую привязывается к импортированному модулю. - Если другое имя не указано, а импортируемый модуль является модулем верхнего уровня, имя модуля привязывается в локальном пространстве имен как ссылка на импортированный модуль
- Если импортируемый модуль не является модулем верхнего уровня, то имя верхнего уровня пакета, содержащего модуль, привязывается в локальном пространстве имен как ссылка на пакет верхнего уровня. К импортированному модулю необходимо обращаться с использованием его полного квалифицированного имени, а не напрямую.
Форма from использует немного более сложный процесс:
- найти модуль, указанный в
fromчасти, загрузить и инициализировать его при необходимости; -
для каждого из идентификаторов, указанных в
importчастях:- проверить, есть ли у импортированного модуля атрибут с таким именем
- если нет, попытаться импортировать подмодуль с этим именем, а затем снова проверить импортированный модуль на наличие этого атрибута
- если атрибут не найден, генерируется исключение
ImportError. - в противном случае ссылка на это значение сохраняется в локальном пространстве имен, используя имя в
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() предоставлен для поддержки приложений, которые динамически определяют модули для загрузки.
Вызывает событие аудита аудита import с аргументами module, filename, sys.path, sys.meta_path, sys.path_hooks.
7.11.1. Операторы
future_stmt ::= "from" "__future__" "import" feature ["as" identifier]
("," feature ["as" identifier])*
| "from" "__future__" "import" "(" feature ["as" identifier]
("," feature ["as" identifier])* [","] ")"
feature ::= identifier
Оператор будущего — это директива компилятору, указывающая, что определённый модуль должен быть скомпилирован с помощью синтаксиса или семантики, которые будут доступны в указанной будущей версии Python, где эта функция станет стандартной.
Оператор будущего предназначен для облегчения миграции на будущие версии Python, которые вводят несовместимые изменения в язык. Он позволяет использовать новые функции на уровне модуля до выпуска, в котором функция становится стандартной.
future_stmt ::= "from" "__future__" "import" feature ["as" identifier]
("," feature ["as" identifier])*
| "from" "__future__" "import" "(" feature ["as" identifier]
("," feature ["as" identifier])* [","] ")"
feature ::= identifier
Оператор будущего должен появляться в начале модуля. Перед оператором будущего могут находиться:
- строка документации модуля (если есть),
- комментарии,
- пустые строки и
- другие операторы будущего.
Единственная функция, требующая использования оператора будущего, это annotations (см. PEP 563).
Все исторические функции, активированные оператором будущего, всё ещё распознаются Python 3. Список включает absolute_import, division, generators, generator_stop, unicode_literals, print_function, nested_scopes и with_statement. Они все избыточны, потому что всегда включены, и сохраняются только для обратной совместимости.
Оператор будущего распознаётся и обрабатывается особым образом во время компиляции: изменения в семантике основных конструкций часто реализуются путём генерации различного кода. Возможно, даже так, что новая функция вводит новый несовместимый синтаксис (например, новое ключевое слово), в таком случае компилятор может потребоваться для парсинга модуля по-другому. Такие решения нельзя отложить до времени выполнения.
Для любой конкретной версии компилятор знает, какие имена функций были определены, и генерирует ошибку во время компиляции, если оператор будущего содержит функцию, неизвестную ему.
Прямые семантики времени выполнения такие же, как у любого оператора импорта: есть стандартный модуль __future__, описанный позже, и он будет импортирован обычным способом в момент выполнения оператора будущего.
Интересные семантики времени выполнения зависят от конкретной функции, активированной оператором будущего.
Обратите внимание, что в операторе нет ничего особенного:
import __future__ [as name]
Это не оператор будущего; это обычный оператор импорта без специальных семантик или ограничений синтаксиса.
Код, скомпилированный с помощью встроенных функций exec() и compile(), которые встречаются в модуле M содержащем оператор будущего, по умолчанию будет использовать новый синтаксис или семантику, связанные с оператором будущего. Это можно настроить с помощью необязательных аргументов функции compile() — см. документацию этой функции для получения подробностей.
Оператор будущего, введённый в интерактивной оболочке интерпретатора, будет действовать для остальной части сессии интерпретатора. Если интерпретатор запущен с опцией -i, получает имя скрипта для выполнения, а скрипт содержит оператор будущего, он будет действовать в интерактивной сессии, запущенной после выполнения скрипта.
См. также
- PEP 236 - Back to the __future__
-
Оригинальное предложение для механизма __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 заставляет перечисленные идентификаторы ссылаться на ранее связанные переменные в ближайшем охватывающем пространстве имён, исключая глобальные переменные. Это важно, потому что по умолчанию поведение привязки заключается в поиске сначала в локальном пространстве имён. Этот оператор позволяет инкапсулированному коду повторно привязывать переменные за пределами локального пространства имён, кроме глобального (модульного) пространства имён.
Имена, перечисленные в операторе nonlocal, в отличие от имён, перечисленных в операторе global, должны ссылаться на уже существующие привязки в охватывающем пространстве имён (охватывающее пространство имён, в котором должна быть создана новая привязка, нельзя однозначно определить).
Имена, перечисленные в операторе nonlocal, не должны конфликтовать с существующими привязками в локальном пространстве имён.
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/reference/simple_stmts.html