6. Выражения

Эта глава объясняет значение элементов выражений в Python.

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

Если (один из вариантов) правила синтаксиса имеет вид:

name: othername

и никакая семантика не задана, то семантика этой формы name такая же, как у othername.

6.1. Арифметические преобразования

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

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

6.2. Элементарные выражения

Atoms are the most basic elements of expressions. The simplest atoms are names or literals. Forms enclosed in parentheses, brackets or braces are also categorized syntactically as atoms.

Формально синтаксис элементарных выражений выглядит так:

atom:
   | 'True'
   | 'False'
   | 'None'
   | '...'
   | identifier
   | literal
   | enclosure
enclosure:
   | parenth_form
   | list_display
   | dict_display
   | set_display
   | generator_expression
   | yield_atom

6.2.1. Встроенные константы

Ключевые слова True, False и None обозначают встроенные константы. Токен ... обозначает константу Ellipsis.

Вычисление этих элементарных выражений даёт соответствующее значение.

Примечание

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

>>> False = 123
  File "<input>", line 1
   False = 123
   ^^^^^
SyntaxError: cannot assign to False

6.2.2. Идентификаторы (имена)

Идентификатор, встречающийся в роли элементарного выражения, является именем. Лексическое определение см. в разделе Имена (идентификаторы и ключевые слова), а описание именования и связывания — в разделе Именование и связывание.

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

6.2.2.1. Искажение закрытых имён

Если идентификатор, который в тексте встречается внутри определения класса, начинается с двух и более символов подчёркивания и не заканчивается двумя и более подчёркиваниями, он считается закрытым именем этого класса.

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

Преобразование не зависит от синтаксического контекста, в котором используется идентификатор, но искажаются только следующие закрытые идентификаторы:

  • Любое имя, используемое как имя переменной, в которую записывают или из которой читают, а также любое имя атрибута, к которому обращаются.

    Атрибут __name__ вложенных функций, классов и псевдонимов типов при этом не искажается.

  • Имя импортируемого модуля, например __spam в import __spam. Если модуль входит в пакет (то есть его имя содержит точку), имя не искажается, например __foo в import __foo.bar не искажается.

  • Имя импортируемого члена, например __f в from spam import __f.

Правило преобразования определено следующим образом:

  • Перед идентификатором вставляется имя класса, у которого сперва удалены все ведущие подчёркивания, а затем добавлено одно. Например, идентификатор __spam в классе с именем Foo, _Foo или __Foo преобразуется в _Foo__spam.

  • Если имя класса состоит только из подчёркиваний, преобразование никак не изменяет идентификатор. Например, идентификатор __spam в классе с именем _ или __ остаётся без изменений.

6.2.3. Литералы

Литерал — это текстовое представление значения. Python поддерживает числовые, строковые и байтовые литералы. Форматированные строки и шаблонные строки считаются строковыми литералами.

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

Строковые и байтовые литералы могут состоять из нескольких токенов. Подробности см. в разделе Конкатенация строковых литералов.

Обратите внимание: отрицательные и комплексные числа, такие как -3 или 3+4.2j, синтаксически не являются литералами. Это унарные или бинарные арифметические операции с операторами - или +.

Вычисление литерала даёт объект заданного типа (int, float, complex, str, bytes или Template) с заданным значением. Для литералов с плавающей точкой и мнимых литералов значение может быть приближённым.

Формальная грамматика литералов:

literal: strings | NUMBER

6.2.3.1. Литералы и тождественность объектов

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

Особенность реализации CPython

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

>>> x = 7
>>> y = 7
>>> x is y
True

Однако большие целые числа вычисляются в разные объекты:

>>> x = 123456789
>>> y = 123456789
>>> x is y
False

Это поведение может измениться в будущих версиях CPython. В частности, граница между «малыми» и «большими» целыми числами уже менялась в прошлом.

CPython выдаст SyntaxWarning при сравнении литералов с помощью is:

>>> x = 7
>>> x is 7
<input>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?
True

См. When can I rely on identity tests with the is operator? для дополнительной информации.

Шаблонные строки неизменяемы, но могут ссылаться на изменяемые объекты как значения Interpolation. В рамках этого раздела две t-строки имеют «одинаковое значение», если совпадают и их структура, и идентичность значений.

В настоящее время каждое вычисление шаблонной строки даёт новый объект.

6.2.3.2. Конкатенация строковых литералов

Несколько расположенных рядом строковых или байтовых литералов, возможно, с разными способами записи кавычек, допускаются, и их значение совпадает с их конкатенацией:

>>> "привет" 'мир'
"приветмир"

Эта возможность определена на синтаксическом уровне, поэтому работает только с литералами. Для конкатенации строковых выражений во время выполнения можно использовать оператор „+“:

>>> greeting = "Привет"
>>> space = " "
>>> name = "Блез"
>>> print(greeting + space + name)   # а не: print(greeting space name)
Привет Блез

Конкатенация литералов позволяет свободно смешивать сырые строки, строки в тройных кавычках и форматированные строковые литералы. Например:

>>> "Привет" r', ' f"{name}!"
"Привет, Блез!"

Эту возможность можно использовать, чтобы уменьшить число необходимых обратных слешей, удобно разбивать длинные строки по нескольким строкам кода или даже добавлять комментарии к частям строк. Например:

re.compile("[A-Za-z_]"       # буква или подчёркивание
           "[A-Za-z0-9_]*"   # буква, цифра или подчёркивание
          )

Однако байтовые литералы можно объединять только с другими байтовыми литералами, но не со строковыми литералами любого вида. Также шаблонные строковые литералы можно объединять только с другими шаблонными строковыми литералами:

>>> t"Привет" t"{name}!"
Template(strings=('Привет', '!'), interpolations=(...))

Формально:

strings: (STRING | fstring)+ | tstring+

6.2.4. Parenthesized forms

A parenthesized form is an optional expression list enclosed in parentheses:

parenth_form: "(" [starred_expression] ")"

A parenthesized expression list yields whatever that expression list yields: if the list contains at least one comma, it yields a tuple; otherwise, it yields the single expression that makes up the expression list.

An empty pair of parentheses yields an empty tuple object. Since tuples are immutable, the same rules as for literals apply (i.e., two occurrences of the empty tuple may or may not yield the same object).

Note that tuples are not formed by the parentheses, but rather by use of the comma. The exception is the empty tuple, for which parentheses are required — allowing unparenthesized «nothing» in expressions would cause ambiguities and allow common typos to pass uncaught.

6.2.5. Displays for lists, sets and dictionaries

For constructing a list, a set or a dictionary Python provides special syntax called «displays», each of them in two flavors:

  • either the container contents are listed explicitly, or

  • they are computed via a set of looping and filtering instructions, called a comprehension.

Common syntax elements for comprehensions are:

comprehension: assignment_expression comp_for
comp_for:      ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter:     comp_for | comp_if
comp_if:       "if" or_test [comp_iter]

The comprehension consists of a single expression followed by at least one for clause and zero or more for or if clauses. In this case, the elements of the new container are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce an element each time the innermost block is reached.

However, aside from the iterable expression in the leftmost for clause, the comprehension is executed in a separate implicitly nested scope. This ensures that names assigned to in the target list don’t «leak» into the enclosing scope.

The iterable expression in the leftmost for clause is evaluated directly in the enclosing scope and then passed as an argument to the implicitly nested scope. Subsequent for clauses and any filter condition in the leftmost for clause cannot be evaluated in the enclosing scope as they may depend on the values obtained from the leftmost iterable. For example: [x*y for x in range(10) for y in range(x, x+10)].

Чтобы включение всегда давало контейнер соответствующего типа, выражения yield и yield from запрещены в неявно вложенной области видимости.

Since Python 3.6, in an async def function, an async for clause may be used to iterate over a asynchronous iterator. A comprehension in an async def function may consist of either a for or async for clause following the leading expression, may contain additional for or async for clauses, and may also use await expressions.

If a comprehension contains async for clauses, or if it contains await expressions or other asynchronous comprehensions anywhere except the iterable expression in the leftmost for clause, it is called an asynchronous comprehension. An asynchronous comprehension may suspend the execution of the coroutine function in which it appears. See also PEP 530.

Добавлено в версии 3.6: Asynchronous comprehensions were introduced.

Изменено в версии 3.8: Теперь yield и yield from запрещены в неявно вложенной области видимости.

Изменено в версии 3.11: Теперь асинхронные включения разрешены внутри включений в асинхронных функциях. Внешние включения неявно становятся асинхронными.

6.2.6. Явные представления списков

A list display is a possibly empty series of expressions enclosed in square brackets:

list_display: "[" [flexible_expression_list | comprehension] "]"

A list display yields a new list object, the contents being specified by either a list of expressions or a comprehension. When a comma-separated list of expressions is supplied, its elements are evaluated from left to right and placed into the list object in that order. When a comprehension is supplied, the list is constructed from the elements resulting from the comprehension.

6.2.7. Явные представления множеств

A set display is denoted by curly braces and distinguishable from dictionary displays by the lack of colons separating keys and values:

set_display: "{" (flexible_expression_list | comprehension) "}"

A set display yields a new mutable set object, the contents being specified by either a sequence of expressions or a comprehension. When a comma-separated list of expressions is supplied, its elements are evaluated from left to right and added to the set object. When a comprehension is supplied, the set is constructed from the elements resulting from the comprehension.

An empty set cannot be constructed with {}; this literal constructs an empty dictionary.

6.2.8. Явные представления словарей

A dictionary display is a possibly empty series of dict items (key/value pairs) enclosed in curly braces:

dict_display:       "{" [dict_item_list | dict_comprehension] "}"
dict_item_list:     dict_item ("," dict_item)* [","]
dict_item:          expression ":" expression | "**" or_expr
dict_comprehension: expression ":" expression comp_for

A dictionary display yields a new dictionary object.

If a comma-separated sequence of dict items is given, they are evaluated from left to right to define the entries of the dictionary: each key object is used as a key into the dictionary to store the corresponding value. This means that you can specify the same key multiple times in the dict item list, and the final dictionary’s value for that key will be the last one given.

A double asterisk ** denotes dictionary unpacking. Its operand must be a mapping. Each mapping item is added to the new dictionary. Later values replace values already set by earlier dict items and earlier dictionary unpackings.

Добавлено в версии 3.5: Распаковка в явные представления словарей, изначально предложенная в PEP 448.

A dict comprehension, in contrast to list and set comprehensions, needs two expressions separated with a colon followed by the usual «for» and «if» clauses. When the comprehension is run, the resulting key and value elements are inserted in the new dictionary in the order they are produced.

Restrictions on the types of the key values are listed earlier in section Иерархия стандартных типов. (To summarize, the key type should be hashable, which excludes all mutable objects.) Clashes between duplicate keys are not detected; the last value (textually rightmost in the display) stored for a given key value prevails.

Изменено в версии 3.8: До Python 3.8 порядок вычисления ключа и значения во включениях словарей не был строго определён. В CPython значение вычислялось раньше ключа. Начиная с версии 3.8 ключ вычисляется раньше значения, как предложено в PEP 572.

6.2.9. Генераторные выражения

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

>>> iterator = (x ** 2 for x in range(10))
>>> iterator
<generator object <genexpr> at ...>

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

>>> list(iterator)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Таким образом, пример выше примерно эквивалентен определению и вызову следующей генераторной функции:

def make_generator_of_squares(iterator):
    for x in iterator:
        yield x ** 2

make_generator_of_squares(iter(range(10)))

Скобки вокруг генераторного выражения можно опустить в вызовах, если оно — единственный позиционный аргумент и именованных аргументов нет. Подробности см. в разделе «Вызовы». Например:

# Скобки после `sum` — часть синтаксиса вызова:
>>> sum(x ** 2 for x in range(10))
285

# Генератору нужны собственные скобки, если он не единственный аргумент:
>>> sum((x ** 2 for x in range(10)), start=1000)
1285

Итерируемое выражение в самой левой части for вычисляется немедленно, поэтому ошибка, возбуждаемая этим выражением, возникнет в месте определения генераторного выражения, а не в месте получения первого значения:

>>> (x ** 2 for x in nonexistent_iterable)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_iterable' is not defined

После вычисления выражения из его результата создаётся итератор, как если бы для него была вызвана iter(). Любая ошибка, возбуждаемая при создании итератора, также возникает немедленно:

>>> (x ** 2 for x in None)
Traceback (most recent call last):
  ...
TypeError: 'NoneType' object is not iterable

Все остальные выражения вычисляются лениво, так же, как в обычных генераторах (то есть когда итератор просят выдать значение):

>>> iterator = (nonexistent_value for x in range(10))
>>> iterator
<generator object <genexpr> at ...>
>>> list(iterator)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_value' is not defined
>>> iterator = (x * y for x in range(10) for y in nonexistent_iterable)
>>> iterator
<generator object <genexpr> at ...>
>>> list(iterator)
Traceback (most recent call last):
  ...
NameError: name 'nonexistent_iterable' is not defined

Чтобы не нарушать ожидаемую работу самого генераторного выражения, выражения yield и yield from запрещены внутри неявно вложенной области видимости.

Если генераторное выражение содержит либо части async for, либо выражения await, оно называется асинхронным генераторным выражением. Асинхронное генераторное выражение возвращает новый объект асинхронного генератора, который является асинхронным итератором (см. Асинхронные итераторы).

Формальная грамматика генераторных выражений:

generator_expression: "(" expression comp_for ")"

Добавлено в версии 3.6: Были представлены асинхронные генераторные выражения.

Изменено в версии 3.7: До Python 3.7 асинхронные генераторные выражения могли появляться только в сопрограммах async def. Начиная с версии 3.7 асинхронные генераторные выражения могут использоваться в любой функции.

Изменено в версии 3.8: Теперь yield и yield from запрещены в неявно вложенной области видимости.

6.2.10. Выражения yield

yield_atom:       "(" yield_expression ")"
yield_from:       "yield" "from" expression
yield_expression: "yield" yield_list | yield_from

Выражение yield используется при определении генераторной функции или асинхронной генераторной функции, и поэтому его можно использовать только в теле определения функции. Использование выражения yield в теле функции делает эту функцию генераторной, а его использование в теле функции async def делает эту сопрограммную функцию асинхронной генераторной функцией. Например:

def gen():  # определяет генераторную функцию
    yield 123

async def agen(): # определяет асинхронную генераторную функцию
    yield 123

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

Изменено в версии 3.8: Теперь выражения yield запрещены в неявно вложенных областях видимости, используемых для реализации включений и генераторных выражений.

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

При вызове генераторной функции она возвращает итератор, называемый генератором. Этот генератор затем управляет выполнением генераторной функции. Выполнение начинается при вызове одного из методов генератора. В этот момент выполнение доходит до первого выражения yield, где снова приостанавливается, возвращая вызывающей стороне генератора значение yield_list или None, если yield_list опущен. Под приостановкой понимается, что сохраняется всё локальное состояние: текущие привязки локальных переменных, указатель инструкций, внутренний стек вычислений и состояние обработки любых исключений. Когда выполнение возобновляется вызовом одного из методов генератора, функция может продолжить работу точно так, как если бы выражение yield было обычным внешним вызовом. Значение выражения yield после возобновления зависит от метода, который возобновил выполнение. Если используется __next__() (обычно через for или встроенную функцию next()), результат равен None. В противном случае, если используется send(), результатом будет значение, переданное в этот метод.

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

Выражения yield разрешены в любом месте конструкции try. Если генератор не возобновляется до его финализации (при достижении нулевого счётчика ссылок или при сборке мусора), вызывается метод close() генераторного итератора, что позволяет выполниться всем ожидающим частям finally.

При использовании yield from <expr> переданное выражение должно быть итерируемым объектом. Значения, получаемые при переборе этого итерируемого объекта, передаются напрямую тому, кто вызывает методы текущего генератора. Любые значения, переданные с помощью send(), и любые исключения, переданные с помощью throw(), передаются вложенному итератору, если у него есть соответствующие методы. В противном случае send() возбудит AttributeError или TypeError, а throw() просто немедленно возбудит переданное исключение.

Когда вложенный итератор завершается, атрибут value возбуждённого экземпляра StopIteration становится значением выражения yield. Это значение можно задать явно при возбуждении StopIteration или автоматически, если подитератор является генератором (возвратом значения из подгенератора).

Изменено в версии 3.3: Добавлено выражение yield from <expr>, которое делегирует поток управления подитератору.

Теперь скобки можно опустить, если выражение yield — единственное выражение в правой части инструкции присваивания.

См. также

PEP 255 — Простые генераторы

Предложение о добавлении в Python генераторов и инструкции yield.

PEP 342 — Сопрограммы через расширенные генераторы

Предложение расширить API и синтаксис генераторов, чтобы их можно было использовать как простые сопрограммы.

PEP 380 — Синтаксис делегирования подгенератору

Предложение добавить синтаксис yield_from, упрощающий делегирование подгенераторам.

PEP 525 — Асинхронные генераторы

Предложение, которое расширило PEP 492, добавив возможности генераторов в сопрограммные функции.

6.2.10.1. Generator-iterator methods

This subsection describes the methods of a generator iterator. They can be used to control the execution of a generator function.

Note that calling any of the generator methods below when the generator is already executing raises a ValueError exception.

generator.__next__()

Starts the execution of a generator function or resumes it at the last executed yield expression. When a generator function is resumed with a __next__() method, the current yield expression always evaluates to None. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the yield_list is returned to __next__()“s caller. If the generator exits without yielding another value, a StopIteration exception is raised.

This method is normally called implicitly, e.g. by a for loop, or by the built-in next() function.

generator.send(value)

Resumes the execution and «sends» a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.

generator.throw(value)
generator.throw(type[, value[, traceback]])

Raises an exception at the point where the generator was paused, and returns the next value yielded by the generator function. If the generator exits without yielding another value, a StopIteration exception is raised. If the generator function does not catch the passed-in exception, or raises a different exception, then that exception propagates to the caller.

In typical use, this is called with a single exception instance similar to the way the raise keyword is used.

For backwards compatibility, however, the second signature is supported, following a convention from older versions of Python. The type argument should be an exception class, and value should be an exception instance. If the value is not provided, the type constructor is called to get an instance. If traceback is provided, it is set on the exception, otherwise any existing __traceback__ attribute stored in value may be cleared.

Изменено в версии 3.12: The second signature (type[, value[, traceback]]) is deprecated and may be removed in a future version of Python.

generator.close()

Raises a GeneratorExit exception at the point where the generator function was paused (equivalent to calling throw(GeneratorExit)). The exception is raised by the yield expression where the generator was paused. If the generator function catches the exception and returns a value, this value is returned from close(). If the generator function is already closed, or raises GeneratorExit (by not catching the exception), close() returns None. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. If the generator has already exited due to an exception or normal exit, close() returns None and has no other effect.

Изменено в версии 3.13: If a generator returns a value upon being closed, the value is returned by close().

6.2.10.2. Примеры

Вот простой пример, демонстрирующий поведение генераторов и генераторных функций:

>>> def echo(value=None):
...     print("Выполнение начинается, когда 'next()' вызывается в первый раз.")
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception as e:
...                 value = e
...     finally:
...         print("Не забудьте выполнить очистку при вызове 'close()'.")
...
>>> generator = echo(1)
>>> print(next(generator))
Выполнение начинается, когда 'next()' вызывается в первый раз.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Не забудьте выполнить очистку при вызове 'close()'.

Примеры использования yield from см. в PEP 380: Syntax for Delegating to a Subgenerator в разделе «Что нового в Python».

6.2.10.3. Асинхронные генераторные функции

Наличие выражения yield в функции или методе, определённых с помощью async def, делает эту функцию асинхронной генераторной.

При вызове асинхронной генераторной функции она возвращает асинхронный итератор, называемый объектом асинхронного генератора. Этот объект затем управляет выполнением генераторной функции. Объект асинхронного генератора обычно используется в циклической инструкции async for в сопрограммной функции аналогично тому, как объект генератора используется в инструкции for.

Вызов одного из методов асинхронного генератора возвращает ожидаемый объект, и выполнение начинается, когда этот объект ожидается с помощью await. В этот момент выполнение доходит до первого выражения yield, где снова приостанавливается, возвращая значение yield_list ожидающей сопрограмме. Как и в случае генератора, приостановка означает, что сохраняется всё локальное состояние: текущие привязки локальных переменных, указатель инструкций, внутренний стек вычислений и состояние обработки любых исключений. Когда выполнение возобновляется ожиданием следующего объекта, возвращённого методами асинхронного генератора, функция может продолжить работу точно так, как если бы выражение yield было обычным внешним вызовом. Значение выражения yield после возобновления зависит от метода, который возобновил выполнение. Если используется __anext__(), результат равен None. В противном случае, если используется asend(), результатом будет значение, переданное в этот метод.

Если асинхронный генератор досрочно завершается из-за break, отмены вызывающей задачи или других исключений, код асинхронной очистки генератора будет выполнен и, возможно, возбудит исключения или обратится к контекстным переменным в неожиданном контексте — например, после окончания жизни задач, от которых он зависит, или во время остановки цикла событий, когда вызывается обработчик сборки мусора для асинхронных генераторов. Чтобы этого избежать, вызывающая сторона должна явно закрыть асинхронный генератор, вызвав метод aclose(), чтобы завершить генератор и в итоге отсоединить его от цикла событий.

В асинхронной генераторной функции выражения yield разрешены в любом месте конструкции try. Однако если асинхронный генератор не возобновляется до его финализации (при достижении нулевого счётчика ссылок или при сборке мусора), выражение yield внутри конструкции try может привести к невыполнению ожидающих частей finally. В этом случае ответственность лежит на цикле событий или планировщике, выполняющем асинхронный генератор: они должны вызвать метод aclose() асинхронного генераторного итератора и запустить полученный объект сопрограммы, что позволит выполниться всем ожидающим частям finally.

Чтобы обеспечить финализацию при завершении работы цикла событий, цикл событий должен определить функцию-финализатор, которая принимает асинхронный генераторный итератор и, как ожидается, вызывает aclose() и выполняет сопрограмму. Этот финализатор можно зарегистрировать вызовом sys.set_asyncgen_hooks(). При первом переборе элементов асинхронный генераторный итератор сохраняет зарегистрированный финализатор, который будет вызван при финализации. Образец финализатора см. в реализации asyncio.BaseEventLoop._asyncgen_finalizer_hook в Lib/asyncio/base_events.py.

Выражение yield from <expr> является синтаксической ошибкой при использовании в асинхронной генераторной функции.

6.2.10.4. Asynchronous generator-iterator methods

This subsection describes the methods of an asynchronous generator iterator, which are used to control the execution of a generator function.

async agen.__anext__()

Returns an awaitable which when run starts to execute the asynchronous generator or resumes it at the last executed yield expression. When an asynchronous generator function is resumed with an __anext__() method, the current yield expression always evaluates to None in the returned awaitable, which when run will continue to the next yield expression. The value of the yield_list of the yield expression is the value of the StopIteration exception raised by the completing coroutine. If the asynchronous generator exits without yielding another value, the awaitable instead raises a StopAsyncIteration exception, signalling that the asynchronous iteration has completed.

This method is normally called implicitly by a async for loop.

async agen.asend(value)

Returns an awaitable which when run resumes the execution of the asynchronous generator. As with the send() method for a generator, this «sends» a value into the asynchronous generator function, and the value argument becomes the result of the current yield expression. The awaitable returned by the asend() method will return the next value yielded by the generator as the value of the raised StopIteration, or raises StopAsyncIteration if the asynchronous generator exits without yielding another value. When asend() is called to start the asynchronous generator, it must be called with None as the argument, because there is no yield expression that could receive the value.

async agen.athrow(value)
async agen.athrow(type[, value[, traceback]])

Returns an awaitable that raises an exception of type type at the point where the asynchronous generator was paused, and returns the next value yielded by the generator function as the value of the raised StopIteration exception. If the asynchronous generator exits without yielding another value, a StopAsyncIteration exception is raised by the awaitable. If the generator function does not catch the passed-in exception, or raises a different exception, then when the awaitable is run that exception propagates to the caller of the awaitable.

Изменено в версии 3.12: The second signature (type[, value[, traceback]]) is deprecated and may be removed in a future version of Python.

async agen.aclose()

Returns an awaitable that when run will throw a GeneratorExit into the asynchronous generator function at the point where it was paused. If the asynchronous generator function then exits gracefully, is already closed, or raises GeneratorExit (by not catching the exception), then the returned awaitable will raise a StopIteration exception. Awaitables returned by subsequent calls to __anext__() or asend() will raise a StopAsyncIteration exception. If the asynchronous generator yields a value, a RuntimeError is raised by the awaitable. If the asynchronous generator raises any other exception, it is propagated to the caller of the awaitable. If the asynchronous generator has already exited due to an exception or normal exit, then further calls to aclose() will return an awaitable that does nothing.

6.3. Первичные выражения

Первичные выражения представляют операции языка с самым высоким приоритетом. Их синтаксис:

primary: atom | attributeref | subscription | call

6.3.1. Обращения к атрибутам

Обращение к атрибуту — это первичное выражение, за которым следуют точка и имя:

attributeref: primary "." identifier

Первичное выражение должно вычисляться в объект типа, поддерживающего обращения к атрибутам, что и делает большинство объектов. Затем у этого объекта запрашивается атрибут, имя которого задано идентификатором. Тип и значение результата определяет сам объект. Многократные вычисления одного и того же обращения к атрибуту могут давать разные объекты.

Поведение такого обращения можно настроить, переопределив метод __getattribute__() или метод __getattr__(). Сначала вызывается метод __getattribute__(), который либо возвращает значение, либо возбуждает AttributeError, если атрибут недоступен.

Если возникает AttributeError и у объекта есть метод __getattr__(), то он вызывается как запасной вариант.

6.3.2. Индексирование и срезы

Синтаксис индексирования обычно используется для выбора элемента из контейнера — например, для получения значения из dict:

>>> digits_by_name = {'один': 1, 'два': 2}
>>> digits_by_name['два']  # Индексирование словаря по ключу 'два'
2

В синтаксисе индексирования за индексируемым объектом — первичным выражением — следует индексатор в квадратных скобках. В простейшем случае индексатор — одно выражение.

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

>>> colors = ['красный', 'синий', 'зелёный', 'чёрный']
>>> colors[3]  # Индексирование списка по индексу 3
'чёрный'

>>> list[str]  # Параметризация типа list аргументом типа str
list[str]

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

Чтобы показать, как работает индексирование, можно определить собственный объект, реализующий __getitem__() и выводящий значение индексатора:

>>> class SubscriptionDemo:
...     def __getitem__(self, key):
...         print(f'обращение по индексатору: {key!r}')
...
>>> demo = SubscriptionDemo()
>>> demo[1]
обращение по индексатору: 1
>>> demo['а' * 3]
обращение по индексатору: 'ааа'

О том, как встроенные типы обрабатывают индексирование, см. в документации __getitem__().

Индексирование может также использоваться как цель в инструкциях присваивания или удаления. В этих случаях интерпретатор вызывает у индексируемого объекта специальный метод __setitem__() или __delitem__() соответственно вместо __getitem__().

>>> colors = ['красный', 'синий', 'зелёный', 'чёрный']
>>> colors[3] = 'белый'  # Установка элемента по индексу
>>> colors
['красный', 'синий', 'зелёный', 'белый']
>>> del colors[3]  # Удаление элемента с индексом 3
>>> colors
['красный', 'синий', 'зелёный']

Все продвинутые формы индексатора, описанные в следующих разделах, также можно использовать для присваивания и удаления.

6.3.2.1. Срезы

Более продвинутая форма индексирования, получение среза, обычно используется для извлечения части последовательности. В этой форме индексатор — это срез: до трёх выражений, разделённых двоеточиями. Любое из выражений можно опустить, но срез должен содержать хотя бы одно двоеточие:

>>> number_names = ['ноль', 'один', 'два', 'три', 'четыре', 'пять']
>>> number_names[1:3]
['один', 'два']
>>> number_names[1:]
['один', 'два', 'три', 'четыре', 'пять']
>>> number_names[:3]
['ноль', 'один', 'два']
>>> number_names[:]
['ноль', 'один', 'два', 'три', 'четыре', 'пять']
>>> number_names[::2]
['ноль', 'два', 'четыре']
>>> number_names[:-3]
['ноль', 'один', 'два']
>>> del number_names[4:]
>>> number_names
['ноль', 'один', 'два', 'три']

При вычислении среза интерпретатор создаёт объект slice, у которого атрибуты start, stop и step соответственно равны результатам выражений между двоеточиями. Любое отсутствующее выражение вычисляется в None. Затем этот объект slice передаётся специальному методу __getitem__() или __class_getitem__(), как и выше.

# продолжение с экземпляром SubscriptionDemo, определённым выше:
>>> demo[2:3]
обращение по индексатору: slice(2, 3, None)
>>> demo[::'spam']
обращение по индексатору: slice(None, None, 'spam')

6.3.2.2. Индексаторы, разделённые запятыми

Индексатор также может задаваться как два или более выражений или срезов, разделённых запятыми:

# продолжение с экземпляром SubscriptionDemo, определённым выше:
>>> demo[1, 2, 3]
обращение по индексатору: (1, 2, 3)
>>> demo[1:2, 3]
обращение по индексатору: (slice(1, 2, None), 3)

Эта форма обычно используется в численных библиотеках для получения срезов многомерных данных. В этом случае интерпретатор создаёт tuple из результатов выражений или срезов и передаёт этот кортеж специальному методу __getitem__() или __class_getitem__(), как и выше.

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

>>> demo['spam',]
обращение по индексатору: ('spam',)

6.3.2.3. Индексирование «со звёздочкой»

Добавлено в версии 3.11: Выражения в tuple_slices могут записываться со звёздочкой. См. PEP 646.

Индексатор может также содержать выражение со звёздочкой. В этом случае интерпретатор распаковывает результат в кортеж и передаёт этот кортеж в __getitem__() или __class_getitem__():

# продолжение с экземпляром SubscriptionDemo, определённым выше:
>>> demo[*range(10)]
обращение по индексатору: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Выражения со звёздочкой можно сочетать с выражениями и срезами, разделёнными запятыми:

>>> demo['а', 'б', *range(3), 'в']
обращение по индексатору: ('а', 'б', 0, 1, 2, 'в')

6.3.2.4. Формальная грамматика индексирования

subscription:     primary '[' subscript ']'
subscript:        single_subscript | tuple_subscript
single_subscript: proper_slice | assignment_expression
proper_slice:     [expression] ":" [expression] [ ":" [expression] ]
tuple_subscript:  ','.(single_subscript | starred_expression)+ [',']

Напомним, что оператор | обозначает упорядоченный выбор. В частности, в subscript, если подходят обе альтернативы, приоритет имеет первая (single_subscript).

6.3.3. Вызовы

Вызов запускает вызываемый объект (например, функцию), передавая ему, возможно, пустой набор аргументов:

call:                 primary "(" [argument_list [","] | comprehension] ")"
argument_list:        positional_arguments ["," starred_and_keywords]
                        ["," keywords_arguments]
                      | starred_and_keywords ["," keywords_arguments]
                      | keywords_arguments
positional_arguments: positional_item ("," positional_item)*
positional_item:      assignment_expression | "*" expression
starred_and_keywords: ("*" expression | keyword_item)
                      ("," "*" expression | "," keyword_item)*
keywords_arguments:   (keyword_item | "**" expression)
                      ("," keyword_item | "," "**" expression)*
keyword_item:         identifier "=" expression

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

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

Если есть именованные аргументы, они сначала преобразуются в позиционные следующим образом. Сначала для формальных параметров создаётся список незаполненных слотов. Если позиционных аргументов N, они помещаются в первые N слотов. Затем для каждого именованного аргумента по идентификатору определяется соответствующий слот (если идентификатор совпадает с именем первого формального параметра, используется первый слот, и так далее). Если слот уже заполнен, возбуждается исключение TypeError. В противном случае аргумент помещается в слот и заполняет его (даже если выражение равно None, оно заполняет слот). Когда все аргументы обработаны, слоты, оставшиеся незаполненными, заполняются соответствующими значениями по умолчанию из определения функции. (Значения по умолчанию вычисляются один раз, при определении функции; поэтому изменяемый объект, например список или словарь, используемый в качестве значения по умолчанию, будет общим для всех вызовов, в которых не указано значение аргумента для соответствующего слота; этого обычно следует избегать.) Если остались незаполненные слоты, для которых значение по умолчанию не задано, возбуждается исключение TypeError. В противном случае список заполненных слотов используется в качестве списка аргументов вызова.

Реализация может предоставлять встроенные функции, у позиционных параметров которых нет имён, даже если для целей документации они «названы», и которые поэтому нельзя передать как именованные аргументы. В CPython так обстоит дело с функциями, написанными на C, которые используют PyArg_ParseTuple() для разбора своих аргументов.

Если позиционных аргументов больше, чем слотов формальных параметров, возбуждается исключение TypeError, если только нет формального параметра, использующего синтаксис *identifier. В этом случае данный формальный параметр получает кортеж, содержащий лишние позиционные аргументы (или пустой кортеж, если лишних позиционных аргументов не было).

Если какой-либо именованный аргумент не соответствует имени формального параметра, возбуждается исключение TypeError, если только нет формального параметра, использующего синтаксис **identifier. В этом случае данный формальный параметр получает словарь, содержащий лишние именованные аргументы (ключами служат имена аргументов, а значениями — переданные значения), или (новый) пустой словарь, если лишних именованных аргументов не было.

Если в вызове функции встречается синтаксис *expression, то expression должно вычисляться в итерируемый объект. Элементы этих итерируемых объектов рассматриваются так, как если бы они были дополнительными позиционными аргументами. Для вызова f(x1, x2, *y, x3, x4), если y вычисляется в последовательность y1, …, yM, это будет эквивалентно вызову с M+4 позиционными аргументами x1, x2, y1, …, yM, x3, x4.

Следствием этого является то, что, хотя синтаксис *expression может стоять после явных именованных аргументов, он обрабатывается до именованных аргументов (и любых аргументов **expression — см. ниже). Так:

>>> def f(a, b):
...     print(a, b)
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2

Редко случается, что в одном вызове используются и именованные аргументы, и синтаксис *expression, поэтому на практике такая путаница возникает нечасто.

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

Когда используется **expression, каждый ключ в этом отображении должен быть строкой. Каждое значение из отображения присваивается первому формальному параметру, допускающему передачу по имени, имя которого равно ключу. Ключ не обязан быть идентификатором Python (например, "max-temp °F" допустим, хотя и не совпадёт ни с одним формальным параметром, который можно объявить). Если ни один формальный параметр не подходит, пара «ключ — значение» собирается параметром **, если он есть, а если его нет, возбуждается исключение TypeError.

Формальные параметры, использующие синтаксис *identifier или **identifier, нельзя использовать как слоты для позиционных аргументов или как имена именованных аргументов.

Изменено в версии 3.5: Вызовы функций принимают любое число распаковок * и **, позиционные аргументы могут следовать за распаковками итерируемых объектов (*), а именованные аргументы — за распаковками словарей (**). Первоначально предложено в PEP 448.

Вызов всегда возвращает некоторое значение, возможно None, если только он не возбуждает исключение. Как это значение вычисляется, зависит от типа вызываемого объекта.

Если это —

пользовательская функция:

Выполняется блок кода функции, которому передаётся список аргументов. Первое, что сделает блок кода, — свяжет формальные параметры с аргументами; это описано в разделе Определения функций. Когда блок кода выполняет инструкцию return, она задаёт возвращаемое значение вызова функции. Если выполнение доходит до конца блока кода, не выполнив инструкцию return, возвращаемое значение равно None.

встроенная функция или метод:

Результат определяется интерпретатором; описания встроенных функций и методов см. в разделе Встроенные функции.

объект класса:

Возвращается новый экземпляр этого класса.

метод экземпляра класса:

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

экземпляр класса:

Класс должен определять метод __call__(); тогда эффект такой же, как если бы был вызван этот метод.

6.4. Выражение await

Приостанавливает выполнение сопрограммы на ожидаемом объекте. Может использоваться только внутри сопрограммной функции.

await_expr: "await" primary

Добавлено в версии 3.5.

6.5. Оператор возведения в степень

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

power: (await_expr | primary) ["**" u_expr]

Таким образом, в последовательности степенных и унарных операторов без скобок операторы вычисляются справа налево (это не ограничивает порядок вычисления операндов): -1**2 даёт -1.

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

Для операндов типа int результат имеет тот же тип, что и операнды, если только второй аргумент не отрицателен. В этом случае все аргументы преобразуются во float и возвращается результат типа float. Например, 10**2 возвращает 100, а 10**-2 возвращает 0.01.

Возведение 0.0 в отрицательную степень приводит к ZeroDivisionError. Возведение отрицательного числа в дробную степень даёт число типа complex. (В более ранних версиях возбуждалось ValueError.)

Эту операцию можно настроить с помощью специальных методов __pow__() и __rpow__().

6.6. Унарные арифметические и побитовые операции

Все унарные арифметические и побитовые операции имеют одинаковый приоритет:

u_expr: power | "-" u_expr | "+" u_expr | "~" u_expr

Унарный оператор - (минус) возвращает значение, противоположное своему числовому аргументу. Операцию можно переопределить с помощью специального метода __neg__().

Унарный оператор + (плюс) возвращает свой числовой аргумент без изменений. Операцию можно переопределить с помощью специального метода __pos__().

Унарный оператор ~ (инверсия) возвращает побитовую инверсию своего целочисленного аргумента. Побитовая инверсия x определяется как -(x+1). Оператор применим только к целым числам и к пользовательским объектам, переопределяющим специальный метод __invert__().

Во всех трёх случаях, если аргумент имеет неподходящий тип, возбуждается исключение TypeError.

6.7. Бинарные арифметические операции

Бинарные арифметические операции имеют привычные уровни приоритета. Обратите внимание, что некоторые из этих операций применимы и к нечисловым типам. Помимо оператора возведения в степень, есть только два уровня: один для мультипликативных операторов и один для аддитивных:

m_expr: u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
        m_expr "//" u_expr | m_expr "/" u_expr |
        m_expr "%" u_expr
a_expr: m_expr | a_expr "+" m_expr | a_expr "-" m_expr

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

Эту операцию можно настроить с помощью специальных методов __mul__() и __rmul__().

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

Оператор @ (собака) предназначен для умножения матриц. Ни один встроенный тип Python не реализует этот оператор.

Эту операцию можно настроить с помощью специальных методов __matmul__() и __rmatmul__().

Добавлено в версии 3.5.

Операторы / (деление) и // (целочисленное деление) возвращают частное своих аргументов. Числовые аргументы сначала приводятся к общему типу. Деление целых чисел даёт float, а целочисленное деление целых чисел — целое число. Результат целочисленного деления вычисляется применением функции «округление вниз» к математическому частному. Деление на ноль возбуждает исключение ZeroDivisionError.

Операцию деления можно настроить с помощью специальных методов __truediv__() и __rtruediv__(). Операцию целочисленного деления можно настроить с помощью специальных методов __floordiv__() и __rfloordiv__().

Оператор % (остаток от деления) возвращает остаток от деления первого аргумента на второй. Числовые аргументы сначала приводятся к общему типу. Нулевой правый аргумент возбуждает исключение ZeroDivisionError. Аргументы могут быть числами с плавающей точкой, например, 3.14%0.7 равно 0.34 (поскольку 3.14 равно 4*0.7 + 0.34). Оператор взятия остатка от деления всегда возвращает результат с тем же знаком, что и у второго операнда (или ноль); абсолютное значение результата строго меньше абсолютного значения второго операнда [1].

Операторы целочисленного деления и взятия остатка от деления связаны следующим тождеством: x == (x//y)*y + (x%y). Целочисленное деление и взятия остатка от деления также связаны со встроенной функцией divmod(): divmod(x, y) == (x//y, x%y). [2].

Помимо выполнения операции взятия остатка над числами, оператор % также перегружен строковыми объектами для форматирования строк в старом стиле (оно же интерполяция). Синтаксис форматирования строк описан в справочнике по библиотеке Python, в разделе printf-style String Formatting.

Операцию остатка можно настроить с помощью специальных методов __mod__() и __rmod__().

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

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

Эту операцию можно настроить с помощью специальных методов __add__() и __radd__().

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

Оператор - (вычитание) возвращает разность своих аргументов. Числовые аргументы сначала приводятся к общему вещественному типу.

Эту операцию можно настроить с помощью специальных методов __sub__() и __rsub__().

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

6.8. Операции сдвига

Операции сдвига имеют более низкий приоритет, чем арифметические операции:

shift_expr: a_expr | shift_expr ("<<" | ">>") a_expr

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

Операцию сдвига влево можно настроить с помощью специальных методов __lshift__() и __rlshift__(). Операцию сдвига вправо можно настроить с помощью специальных методов __rshift__() и __rrshift__().

Сдвиг вправо на n битов определяется как целочисленное деление на pow(2,n). Сдвиг влево на n битов определяется как умножение на pow(2,n).

6.9. Бинарные побитовые операции

Каждая из трёх побитовых операций имеет свой уровень приоритета:

and_expr: shift_expr | and_expr "&" shift_expr
xor_expr: and_expr | xor_expr "^" and_expr
or_expr:  xor_expr | or_expr "|" xor_expr

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

Оператор ^ возвращает побитовое XOR (исключающее ИЛИ) своих аргументов, которые должны быть целыми числами, либо один из них должен быть пользовательским объектом, переопределяющим специальные методы __xor__() или __rxor__().

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

6.10. Сравнения

В отличие от C, все операции сравнения в Python имеют одинаковый приоритет, более низкий, чем у любых арифметических операций, операций сдвига и побитовых операций. Кроме того, в отличие от C, выражения вида a < b < c интерпретируются так, как принято в математике:

comparison:    or_expr (comp_operator or_expr)*
comp_operator: "<" | ">" | "==" | ">=" | "<=" | "!="
               | "is" ["not"] | ["not"] "in"

Сравнения возвращают логические значения: True или False. Пользовательские методы расширенного сравнения могут возвращать значения других типов. В этом случае в логическом контексте Python вызывает для такого значения bool().

Сравнения можно произвольно объединять в цепочки, например, x < y <= z эквивалентно x < y and y <= z, за исключением того, что y вычисляется только один раз (но в обоих случаях z вообще не вычисляется, если обнаружено, что x < y ложно).

Формально, если a, b, c, …, y, z — выражения, а op1, op2, …, opN — операторы сравнения, то a op1 b op2 c ... y opN z эквивалентно a op1 b and b op2 c and ... y opN z, за исключением того, что каждое выражение вычисляется не более одного раза.

Обратите внимание, что a op1 b op2 c не подразумевает никакого сравнения между a и c, так что, например, x < y > z вполне допустимо (хотя, возможно, и некрасиво).

6.10.1. Сравнение значений

Операторы <, >, ==, >=, <= и != сравнивают значения двух объектов. Объекты не обязаны иметь один и тот же тип.

В главе Объекты, значения и типы данных говорится, что у объектов есть значение (помимо типа и идентификатора). Значение объекта — довольно абстрактное понятие в Python: например, не существует канонического метода доступа к значению объекта. Кроме того, нет требования, чтобы значение объекта строилось каким-то определённым образом, например, состояло из всех его атрибутов данных. Операторы сравнения реализуют определённое представление о том, что такое значение объекта. Можно считать, что они определяют значение объекта косвенно, через свою реализацию сравнения.

Поскольку все типы являются (прямыми или косвенными) подтипами object, они наследуют от object поведение сравнения по умолчанию. Типы могут настроить своё поведение при сравнении, реализовав методы расширенного сравнения, такие как __lt__(), описанные в разделе Базовая настройка поведения.

Поведение по умолчанию при сравнении на равенство (== и !=) основано на идентификаторах объектов. Следовательно, сравнение на равенство экземпляров с одинаковыми идентификаторами даёт равенство, а сравнение на равенство экземпляров с разными идентификаторами даёт неравенство. Мотивация такого поведения по умолчанию — желание, чтобы все объекты были рефлексивными (т. е. из x is y следовало x == y).

По умолчанию упорядочивающие сравнения (<, >, <= и >=) не поддерживаются: попытка выполнить такое сравнение возбуждает TypeError. Причина такого поведения — отсутствие инварианта, аналогичного тому, что есть для равенства.

Поведение сравнения на равенство по умолчанию, при котором экземпляры с разными идентификаторами всегда неравны, может расходиться с потребностями типов, у которых есть разумное определение значения объекта и равенства, основанного на значении. Таким типам необходимо настраивать своё поведение при сравнении, и некоторые встроенные типы так и делают.

Следующий список описывает поведение при сравнении наиболее важных встроенных типов.

  • Числа встроенных числовых типов (Numeric Types — int, float, complex) и типов стандартной библиотеки fractions.Fraction и decimal.Decimal можно сравнивать как внутри своих типов, так и между ними, с тем ограничением, что комплексные числа не поддерживают упорядочивающие сравнения. В пределах возможностей задействованных типов они сравниваются математически (алгоритмически) правильно, без потери точности.

    Значения «не число» float('NaN') и decimal.Decimal('NaN') особые. Любое упорядочивающее сравнение числа со значением «не число» ложно. Нелогичное на первый взгляд следствие — значения «не число» не равны сами себе. Например, если x = float('NaN'), то 3 < x, x < 3 и x == x ложны, а x != x истинно. Такое поведение соответствует IEEE 754.

  • None и NotImplemented — синглтоны. В PEP 8 рекомендуется всегда сравнивать синглтоны с помощью is или is not, а не операторов равенства.

  • Двоичные последовательности (экземпляры bytes или bytearray) можно сравнивать как внутри своих типов, так и между ними. Они сравниваются лексикографически по числовым значениям своих элементов.

  • Строки (экземпляры str) сравниваются лексикографически по числовым кодовым позициям Юникода своих символов (результату встроенной функции ord()). [3]

    Строки и двоичные последовательности нельзя сравнивать напрямую.

  • Последовательности (экземпляры tuple, list или range) можно сравнивать только внутри каждого из своих типов, причём объекты range не поддерживают упорядочивающие сравнения. Сравнение на равенство между этими типами даёт неравенство, а упорядочивающее сравнение между этими типами возбуждает TypeError.

    Последовательности сравниваются лексикографически с помощью сравнения соответствующих элементов. Встроенные контейнеры, как правило, считают, что идентичные объекты равны самим себе. Это позволяет им пропускать проверки на равенство для идентичных объектов, чтобы повысить производительность и сохранить свои внутренние инварианты.

    Лексикографическое сравнение встроенных коллекций работает следующим образом:

    • Чтобы две коллекции были равны, они должны быть одного типа, иметь одинаковую длину, а каждая пара соответствующих элементов должна быть равна (например, [1,2] == (1,2) ложно, потому что типы различны).

    • Коллекции, поддерживающие упорядочивающие сравнения, упорядочиваются так же, как их первые неравные элементы (например, [1,2,x] <= [1,2,y] имеет то же значение, что и x <= y). Если соответствующего элемента не существует, первой упорядочивается более короткая коллекция (например, [1,2] < [1,2,3] истинно).

  • Отображения (экземпляры dict) равны тогда и только тогда, когда у них равные пары (key, value). Сравнение на равенство ключей и значений обеспечивает рефлексивность.

    Упорядочивающие сравнения (<, >, <= и >=) возбуждают TypeError.

  • Множества (экземпляры set или frozenset) можно сравнивать как внутри своих типов, так и между ними.

    Для них операторы упорядочивающего сравнения определены как проверки на подмножество и надмножество. Эти отношения не определяют полный порядок (например, множества {1,2} и {2,3} не равны, и ни одно из них не является подмножеством или надмножеством другого). Соответственно, множества не подходят в качестве аргументов функций, которые зависят от полного порядка (например, min(), max() и sorted() дают неопределённые результаты, если на вход подан список множеств).

    Сравнение множеств обеспечивает рефлексивность их элементов.

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

Пользовательские классы, настраивающие своё поведение при сравнении, по возможности должны следовать некоторым правилам согласованности:

  • Сравнение на равенство должно быть рефлексивным. Другими словами, идентичные объекты должны быть равны:

    из x is y следует x == y

  • Сравнение должно быть симметричным. Другими словами, следующие выражения должны давать один и тот же результат:

    x == y и y == x

    x != y и y != x

    x < y и y > x

    x <= y и y >= x

  • Сравнение должно быть транзитивным. Это иллюстрируют следующие (неисчерпывающие) примеры:

    из x > y and y > z следует x > z

    из x < y and y <= z следует x < z

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

    x == y и not x != y

    x < y и not x >= y (для полного порядка)

    x > y и not x <= y (для полного порядка)

    Последние два выражения применимы к коллекциям с полным порядком (например, к последовательностям, но не к множествам и не к отображениям). См. также декоратор @total_ordering.

  • Результат hash() должен быть согласован с равенством. Равные объекты должны либо иметь одинаковое хеш-значение, либо быть помечены как нехешируемые.

Python не принуждает к соблюдению этих правил согласованности. На самом деле значения «не число» — пример того, что эти правила не соблюдаются.

6.10.2. Операции проверки принадлежности

Операторы in и not in проверяют принадлежность. x in s вычисляется в True, если x является элементом s, и в False в противном случае. x not in s возвращает отрицание x in s. Это поддерживают все встроенные последовательности и типы множеств, а также словари, для которых in проверяет, есть ли в словаре заданный ключ. Для контейнерных типов, таких как list, tuple, set, frozenset, dict или collections.deque, выражение x in y эквивалентно any(x is e or x == e for e in y).

Для строковых и байтовых типов x in y равно True тогда и только тогда, когда x является подстрокой y. Эквивалентная проверка — y.find(x) != -1. Пустая строка всегда считается подстрокой любой другой строки, поэтому "" in "abc" вернёт True.

Для пользовательских классов, определяющих метод __contains__(), x in y возвращает True, если y.__contains__(x) возвращает истинное значение, и False в противном случае.

Для пользовательских классов, которые не определяют __contains__(), но определяют __iter__(), x in y равно True, если при итерации по y порождается некоторое значение z, для которого выражение x is z or x == z истинно. Если во время итерации возбуждается исключение, это равносильно тому, что исключение возбудил in.

Наконец, пробуется старый протокол итерации: если класс определяет __getitem__(), x in y равно True тогда и только тогда, когда существует неотрицательный целочисленный индекс i, для которого x is y[i] or x == y[i], и ни один меньший целочисленный индекс не возбуждает исключение IndexError. (Если возбуждается любое другое исключение, это равносильно тому, что исключение возбудил in).

Оператор not in определён так, чтобы его значение истинности было обратным значению in.

6.10.3. Сравнение идентичности

Операторы is и is not проверяют идентификаторы объектов: x is y истинно тогда и только тогда, когда x и y — один и тот же объект. Идентификатор объекта определяется с помощью функции id(). x is not y даёт обратное значение истинности. [4]

6.11. Логические операции

or_test:  and_test | or_test "or" and_test
and_test: not_test | and_test "and" not_test
not_test: comparison | "not" not_test

В контексте логических операций, а также когда выражения используются в инструкциях управления потоком выполнения, следующие значения интерпретируются как ложные: False, None, числовой нуль всех типов, а также пустые строки и контейнеры (включая строки, кортежи, списки, словари, множества и frozenset). Все остальные значения интерпретируются как истинные. Пользовательские объекты могут настроить своё значение истинности, предоставив метод __bool__().

Оператор not возвращает True, если его аргумент ложен, и False в противном случае.

Выражение x and y сначала вычисляет x. Если x ложно, возвращается его значение, в противном случае вычисляется y и возвращается полученное значение.

Выражение x or y сначала вычисляет x. Если x истинно, возвращается его значение, в противном случае вычисляется y и возвращается полученное значение.

Обратите внимание, что ни and, ни or не ограничивают возвращаемое значение и его тип значениями False и True, а возвращают последний вычисленный аргумент. Иногда это полезно: например, если s — строка, которую нужно заменить значением по умолчанию, когда она пуста, то выражение s or 'foo' даёт нужное значение. Поскольку not должен создать новое значение, он возвращает логическое значение независимо от типа своего аргумента (например, not 'foo' даёт False, а не ''.)

6.12. Выражения присваивания

assignment_expression: [identifier ":="] expression

Выражение присваивания (иногда его также называют «именованным выражением» или «моржом») присваивает значение expression идентификатору identifier и одновременно возвращает значение expression.

Один из распространённых случаев применения — обработка найденных совпадений регулярных выражений:

if matching := pattern.search(data):
    do_something(matching)

Или обработка файлового потока по частям:

while chunk := file.read(9000):
    process(chunk)

Выражения присваивания должны быть заключены в круглые скобки, если они используются как инструкции-выражения или как подвыражения в срезах, условных выражениях, лямбдах, именованных аргументов и условиях во включениях, а также в инструкциях assert, with и assignment. Во всех остальных местах, где их можно использовать, скобки не требуются, в том числе в инструкциях if и while.

Добавлено в версии 3.8: Подробнее о выражениях присваивания см. в PEP 572.

6.13. Условные выражения

conditional_expression: or_test ["if" or_test "else" expression]
expression:             conditional_expression | lambda_expr

Условное выражение (иногда его называют «тернарным оператором») — это альтернатива инструкции if-else. Поскольку это выражение, оно возвращает значение и может использоваться как подвыражение.

Выражение x if C else y сначала вычисляет условие C, а не x. Если C истинно, вычисляется x и возвращается его значение, в противном случае вычисляется y и возвращается его значение.

Подробнее об условных выражениях см. в PEP 308.

6.14. Лямбды

lambda_expr: "lambda" [parameter_list] ":" expression

Лямбда-выражения (иногда их называют лямбда-формами) используются для создания анонимных функций. Выражение lambda parameters: expression возвращает объект функции. Этот безымянный объект ведёт себя как объект функции, определённый так:

def <lambda>(parameters):
    return expression

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

6.15. Списки выражений

starred_expression:       "*" or_expr | expression
flexible_expression:      assignment_expression | starred_expression
flexible_expression_list: flexible_expression ("," flexible_expression)* [","]
starred_expression_list:  starred_expression ("," starred_expression)* [","]
expression_list:          expression ("," expression)* [","]
yield_list:               expression_list | starred_expression "," [starred_expression_list]

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

An asterisk * denotes iterable unpacking. Its operand must be an iterable. The iterable is expanded into a sequence of items, which are included in the new tuple, list, or set, at the site of the unpacking.

Добавлено в версии 3.5: Первоначально распаковка итерируемых объектов в списках выражений предложена в PEP 448.

Добавлено в версии 3.11: Любой элемент списка выражений может быть помечен звёздочкой. См. PEP 646.

Завершающая запятая нужна только для создания кортежа из одного элемента, например 1,, а во всех остальных случаях она необязательна. Одиночное выражение без завершающей запятой не создаёт кортеж, а даёт значение этого выражения. (Чтобы создать пустой кортеж, используйте пустую пару круглых скобок: ().)

6.16. Порядок вычислений

Python вычисляет выражения слева направо. Обратите внимание, что при вычислении присваивания правая часть вычисляется раньше левой.

В следующих строках выражения вычисляются в порядке возрастания их числовых суффиксов:

expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2

6.17. Приоритет операторов

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

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

Оператор

Описание

(expressions...),

[expressions...], {key: value...}, {expressions...}

Связывание или выражение в скобках, явное представление списка, явное представление словаря, явное представление множества

x[index], x[index:index] x(arguments...), x.attribute

Индексирование (включая срезы), вызов, обращение к атрибуту

await x

Выражение await

**

Возведение в степень [5]

+x, -x, ~x

Плюс, минус, побитовое НЕ

*, @, /, //, %

Умножение, матричное умножение, деление, целочисленное деление, остаток [6]

+, -

Сложение и вычитание

<<, >>

Сдвиги

&

Побитовое И

^

Побитовое XOR

|

Побитовое ИЛИ

in, not in, is, is not, <, <=, >, >=, !=, ==

Сравнения, включая проверки принадлежности и проверки идентичности

not x

Логическое НЕ

and

Логическое И

or

Логическое ИЛИ

if – else

Условное выражение

lambda

Лямбда-выражение

:=

Выражение присваивания

Примечания