Документация Python неофициальный перевод
Содержание страницы

6. ВыраженияExpressions

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

Примечания к синтаксису: В этой и следующих главах для описания синтаксиса, а не лексического анализа, будет использоваться расширенная нотация БНФ. Когда (одна из альтернатив) синтаксического правила имеет вид

name ::= othername

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

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

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

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

  • в противном случае, если хотя бы один аргумент – число с плавающей запятой, другой преобразуется в число с плавающей запятой;

  • в противном случае оба должны быть целыми числами, и преобразование не требуется.

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

6.2. АтомыAtoms

Атомы – это самые базовые элементы выражений. Простейшие атомы – идентификаторы или литералы. Формы, заключённые в круглые, квадратные или фигурные скобки, также синтаксически относятся к атомам. Синтаксис атомов:

atom      ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display
              | generator_expression | yield_atom

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

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

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

6.2.1.1. Преобразование приватных имёнPrivate name mangling

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

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

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

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

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

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

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

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

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

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

6.2.2. ЛитералыLiterals

Python поддерживает строковые литералы, литералы bytes и различные числовые литералы:

literal ::= stringliteral | bytesliteral
            | integer | floatnumber | imagnumber

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

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

6.2.3. Выражения в скобкахParenthesized forms

Выражение в скобках – это необязательный список выражений, заключённый в круглые скобки:

parenth_form ::= "(" [starred_expression] ")"

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

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

Обратите внимание: кортежи образуются не скобками, а запятой. Исключение – пустой кортеж, для которого скобки обязательны: разрешить выражение без скобок, означающее «ничего», привело бы к двусмысленности и позволило бы типичным опечаткам остаться незамеченными.

6.2.4. Отображения для списков, множеств и словарейDisplays for lists, sets and dictionaries

Для создания списка, множества или словаря в Python предусмотрен специальный синтаксис, называемый «отображениями» (displays); каждый из них существует в двух вариантах:

  • либо содержимое контейнера перечисляется явно, либо

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

Общие синтаксические элементы для включений:

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]

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

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

Итерируемое выражение в самом левом предложении for вычисляется непосредственно в окружающей области видимости, а затем передаётся как аргумент в неявно вложенную область. Последующие предложения for и любое условие фильтрации в самом левом предложении for не могут быть вычислены в окружающей области, поскольку они могут зависеть от значений, полученных из самого левого итерируемого объекта. Например: [x*y for x in range(10) for y in range(x, x+10)].

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

Начиная с Python 3.6, в функции async def предложение async for может использоваться для итерации по асинхронному итератору. Включение в функции async def может состоять из предложения for или async for после ведущего выражения, может содержать дополнительные предложения for или async for, а также может использовать выражения await.

Если включение содержит предложения async for, или содержит выражения await или другие асинхронные включения где-либо, кроме итерируемого выражения в самом левом предложении for, оно называется асинхронным включением. Асинхронное включение может приостанавливать выполнение корутинной функции, в которой оно находится. См. также PEP 530.

Добавлено в версии 3.6: Были введены асинхронные включения.

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

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

6.2.5. Списковые отображенияList displays

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

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

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

6.2.6. Множественные отображенияSet displays

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

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

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

Пустое множество нельзя создать с помощью {}; этот литерал создаёт пустой словарь.

6.2.7. Словарные отображенияDictionary displays

Словарное отображение – это возможно пустая последовательность элементов словаря (пар ключ/значение), заключённая в фигурные скобки:

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

Словарное отображение возвращает новый объект словаря.

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

Двойная звёздочка ** обозначает распаковку словаря. Её операндом должно быть отображение (mapping). Каждый элемент отображения добавляется в новый словарь. Более поздние значения заменяют значения, уже установленные более ранними элементами словаря и более ранними распаковками словарей.

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

Словарное включение, в отличие от списковых и множественных включений, требует двух выражений, разделённых двоеточием, после которых следуют обычные предложения «for» и «if». При выполнении включения результирующие элементы ключей и значений вставляются в новый словарь в порядке их получения.

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

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

6.2.8. Генераторные выраженияGenerator expressions

Генераторное выражение – это компактная запись генератора в круглых скобках:

generator_expression ::= "(" expression comp_for ")"

Генераторное выражение возвращает новый объект-генератор. Его синтаксис такой же, как у включений, за исключением того, что оно заключается в круглые скобки вместо квадратных или фигурных.

Переменные, используемые в генераторном выражении, вычисляются лениво при вызове метода __next__() для объекта-генератора (так же, как и в обычных генераторах). Однако выражение итерируемого объекта в самой левой части for вычисляется немедленно, поэтому ошибка, возникшая в нём, будет выдана в точке определения генераторного выражения, а не при получении первого значения. Последующие части for и любое условие фильтрации в самой левой части for не могут быть вычислены во внешней области видимости, поскольку они могут зависеть от значений, полученных из самого левого итерируемого объекта. Например: (x*y for x in range(10) for y in range(x, x+10)).

Круглые скобки можно опускать при вызовах с одним аргументом. Подробнее см. раздел Вызовы.

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

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

Добавлено в версии 3.6: Появились асинхронные generator-выражения.

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

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

6.2.9. Выражения yieldYield expressions

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

The yield expression is used when defining a generator function or an asynchronous generator function and thus can only be used in the body of a function definition. Using a yield expression in a function’s body causes that function to be a generator function, and using it in an async def function’s body causes that coroutine function to be an asynchronous generator function. For example:

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

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

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

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

Generator functions are described below, while asynchronous generator functions are described separately in section Asynchronous generator functions.

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

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

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

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

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

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

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

См. также

PEP 255 - Simple Generators

Предложение по добавлению генераторов и оператора yield в Python.

PEP 342 - Coroutines via Enhanced Generators

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

PEP 380 - Syntax for Delegating to a Subgenerator

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

PEP 525 - Asynchronous Generators

The proposal that expanded on PEP 492 by adding generator capabilities to coroutine functions.

6.2.9.1. Методы generator-итератораGenerator-iterator methods

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

Обратите внимание, что вызов любого из приведённых ниже методов генератора, когда генератор уже выполняется, приводит к исключению ValueError.

generator.__next__()

Запускает выполнение генераторной функции или возобновляет его с последнего выполненного выражения yield. При возобновлении генераторной функции методом __next__() текущее выражение yield всегда вычисляется в None. Затем выполнение продолжается до следующего выражения yield, на котором генератор снова приостанавливается, и значение yield_list возвращается вызывающему коду __next__(). Если генератор завершается, не выдав следующего значения, возбуждается исключение StopIteration.

Обычно этот метод вызывается неявно, например, циклом for или встроенной функцией next().

generator.send(value)

Возобновляет выполнение и «отправляет» значение в генераторную функцию. Аргумент value становится результатом текущего выражения yield. Метод send() возвращает следующее значение, выданное генератором, или возбуждает StopIteration, если генератор завершается, не выдав другого значения. При вызове send() для запуска генератора его необходимо вызывать с аргументом None, так как нет выражения yield, которое могло бы получить значение.

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

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

Обычно этот метод вызывается с одним экземпляром исключения, подобно тому, как используется ключевое слово raise.

Однако для обратной совместимости поддерживается вторая сигнатура, следуя соглашению из более старых версий Python. Аргумент type должен быть классом исключения, а value – экземпляром исключения. Если value не указан, вызывается конструктор type для получения экземпляра. Если traceback предоставлен, он устанавливается в исключении, в противном случае любой существующий атрибут __traceback__, хранящийся в value, может быть очищен.

Изменено в версии 3.12: Вторая сигнатура (type[, value[, traceback]]) является устаревшей и может быть удалена в будущей версии Python.

generator.close()

Возбуждает GeneratorExit в точке, где была приостановлена функция-генератор. Если после этого функция-генератор завершается штатно, уже закрыта или возбуждает GeneratorExit (не перехватывая исключение), close возвращается к вызвавшему коду. Если генератор выдает значение, возбуждается RuntimeError. Если генератор возбуждает любое другое исключение, оно передается вызвавшему коду. close() ничего не делает, если генератор уже завершился из-за исключения или штатно.

6.2.9.2. ПримерыExamples

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

>>> def echo(value=None):
...     print("Execution starts when 'next()' is called for the first time.")
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception as e:
...                 value = e
...     finally:
...         print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
Execution starts when 'next()' is called for the first time.
1
>>> print(next(generator))
None
>>> print(generator.send(2))
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

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

6.2.9.3. Асинхронные генераторные функцииAsynchronous generator functions

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

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

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

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

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

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

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

6.2.9.4. Методы итератора асинхронного генератораAsynchronous generator-iterator methods

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

async agen.__anext__()

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

Обычно этот метод вызывается неявно циклом async for.

async agen.asend(value)

Возвращает ожидаемый объект, который при запуске возобновляет выполнение асинхронного генератора. Как и в случае метода send() для генератора, этот «отправляет» значение в асинхронную функцию-генератор, и аргумент value становится результатом текущего выражения yield. Ожидаемый объект, возвращённый методом asend(), вернёт следующее значение, выданное генератором, как значение возбуждённого StopIteration, или возбуждает StopAsyncIteration, если асинхронный генератор завершится, не выдав другого значения. Когда asend() вызывается для запуска асинхронного генератора, он должен быть вызван с аргументом None, потому что нет выражения yield, которое могло бы получить значение.

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

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

Изменено в версии 3.12: Вторая сигнатура (type[, value[, traceback]]) является устаревшей и может быть удалена в будущей версии Python.

async agen.aclose()

Возвращает ожидаемый объект, который при запуске вызовет GeneratorExit в асинхронную функцию-генератор в точке, где она была приостановлена. Если асинхронная функция-генератор затем завершается нормально, уже закрыта или возбуждает GeneratorExit (не перехватив исключение), то возвращаемый ожидаемый объект возбудит исключение StopIteration. Любые последующие ожидаемые объекты, возвращённые вызовами асинхронного генератора, будут возбуждать исключение StopAsyncIteration. Если асинхронный генератор выдаёт значение, ожидаемый объект возбуждает RuntimeError. Если асинхронный генератор возбуждает любое другое исключение, оно распространяется на вызывающую сторону ожидаемого объекта. Если асинхронный генератор уже завершился по причине исключения или нормального завершения, то последующие вызовы aclose() возвратят ожидаемый объект, который ничего не делает.

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

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

primary ::= atom | attributeref | subscription | slicing | call

6.3.1. Ссылки на атрибутыAttribute references

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

attributeref ::= primary "." identifier

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

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

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

6.3.2. ИндексацияSubscriptions

The subscription of an instance of a container class will generally select an element from the container. The subscription of a generic class will generally return a GenericAlias object.

subscription ::= primary "[" flexible_expression_list "]"

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

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

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

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

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

  1. Отображения. Если первичный объект является отображением, то список выражений должен вычисляться в объект, значение которого является одним из ключей отображения, и индексация выбирает значение в отображении, соответствующее этому ключу. Примером встроенного класса отображения является класс dict.

  2. Последовательности. Если первичный объект является последовательностью, то список выражений должен вычисляться в int или slice (как описано в следующем разделе). Примеры встроенных классов последовательностей включают классы str, list и tuple.

Формальный синтаксис не предусматривает особой обработки отрицательных индексов в последовательностях. Однако все встроенные последовательности предоставляют метод __getitem__(), который интерпретирует отрицательные индексы, добавляя к индексу длину последовательности, так что, например, x[-1] выбирает последний элемент x. Результирующее значение должно быть неотрицательным целым числом, меньшим количества элементов в последовательности, и индексация выбирает элемент с этим индексом (начиная с нуля). Поскольку поддержка отрицательных индексов и срезов реализована в методе __getitem__() объекта, подклассы, переопределяющие этот метод, должны явно добавить эту поддержку.

string – это особый вид последовательности, элементами которой являются символы. Символ не является отдельным типом данных, а представляет собой строку ровно из одного символа.

6.3.3. СрезыSlicings

Срез выбирает диапазон элементов в объекте-последовательности (например, строке, кортеже или списке). Срезы могут использоваться как выражения или как цели в операторах присваивания или del. Синтаксис среза:

slicing      ::= primary "[" slice_list "]"
slice_list   ::= slice_item ("," slice_item)* [","]
slice_item   ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound  ::= expression
upper_bound  ::= expression
stride       ::= expression

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

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

6.3.4. ВызовыCalls

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

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: Реализация может предоставлять встроенные функции, чьи позиционные параметры не имеют имён, даже если они «названы» для целей документации, и поэтому их нельзя передать по ключевому слову. В 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. Выражение awaitAwait expression

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

await_expr ::= "await" primary

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

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

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

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. Унарные арифметические и побитовые операцииUnary arithmetic and bitwise operations

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

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

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

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

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

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

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

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

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__().

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

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

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

Операторы / (деления) и // (целочисленного деления) возвращают частное своих аргументов. Числовые аргументы сначала преобразуются к общему типу. Деление целых чисел даёт число с плавающей точкой, а целочисленное деление целых чисел даёт целое число; результат соответствует математическому делению с применением функции «floor» к результату. Деление на ноль вызывает исключение 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.

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

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

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

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

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

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

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

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

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

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

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

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

6.9. Двоичные побитовые операцииBinary bitwise operations

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

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

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

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

6.10. СравненияComparisons

В отличие от 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. Сравнения значенийValue comparisons

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

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

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

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

Поведение сравнения порядка по умолчанию (<, >, <= и >=) не предусмотрено; попытка вызывает TypeError. Мотивация такого поведения по умолчанию – отсутствие аналогичного инварианта, как для равенства.

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

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

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

    Значения «не число» (NaN) 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) сравниваются лексикографически по числовым кодовым точкам Unicode (результат встроенной функции ord()) своих символов. [3]

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

  • Последовательности (экземпляры tuple, list или 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 не требует соблюдения этих правил согласованности. Фактически, значения «не число» (NaN) являются примером их нарушения.

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

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

Для типов str и bytes 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. Сравнение идентичностиIdentity comparisons

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

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

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, числовой ноль всех типов, а также пустые строки и контейнеры (включая строки, кортежи, списки, словари, множества и неизменяемые множества). Все остальные значения интерпретируются как истинные. Пользовательские объекты могут настраивать своё логическое значение, предоставив метод __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 expressions

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 expressions

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

Условные выражения (иногда называемые «тернарным оператором») имеют самый низкий приоритет среди всех операций Python.

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

См. PEP 308 для получения дополнительных сведений об условных выражениях.

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

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

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

def <lambda>(parameters):
    return expression

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

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

starred_expression       ::= ["*"] or_expr
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]

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

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

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

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

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

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

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. Приоритет операторовOperator precedence

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

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

Оператор

Описание

(expressions...),

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

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

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

Индексация, срез, вызов, ссылка на атрибут

await x

Выражение await

**

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

+x, -x, ~x

Унарный плюс, унарный минус, побитовое НЕ

*, @, /, //, %

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

+, -

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

<<, >>

Сдвиги

&

Побитовое И

^

Побитовое исключающее ИЛИ

|

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

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

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

not x

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

and

Логическое И

or

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

ifelse

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

lambda

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

:=

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

Сноски