6. Выражения

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

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

name ::=  othername

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

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

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

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

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

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

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

6.2. Атомы

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

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

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

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

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

Искажение частных имен: Когда идентификатор, который текстуально встречается в определении класса, начинается с двух или более символов подчеркивания и не заканчивается двумя или более символами подчеркивания, он считается private name этого класса. Частные имена преобразуются в более длинную форму до того, как для них генерируется код. Преобразование вставляет перед именем имя класса с удаленными ведущими символами подчеркивания и вставленным одним символом подчеркивания. Например, идентификатор __spam, встречающийся в классе с именем Ham, будет преобразован в _Ham__spam. Это преобразование не зависит от синтаксического контекста, в котором используется идентификатор. Если преобразованное имя очень длинное (более 255 символов), может произойти усечение, определенное реализацией. Если имя класса состоит только из символов подчеркивания, преобразование не выполняется.

6.2.2. Литература

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

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

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

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

6.2.3. Парентезные формы

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

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

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

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

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

6.2.4. Дисплеи для списков, наборов и словарей

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

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

  • они вычисляются с помощью набора инструкций циклов и фильтрации, называемых 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 может использоваться предложение asynchronous iterator. Понимание в функции async def может состоять из предложения for или async for, следующего за ведущим выражением, может содержать дополнительные предложения for или async for, а также использовать выражения await. Если вычисление содержит либо async for клаузулы, либо await выражения, оно называется asynchronous comprehension. Асинхронное понимание может приостановить выполнение функции coroutine, в которой оно появляется. См. также PEP 530.

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

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

6.2.5. Отображение списка

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

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

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

6.2.6. Установить дисплеи

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

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

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

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

6.2.7. Отображения в словаре

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

dict_display       ::=  "{" [key_datum_list | dict_comprehension] "}"
key_datum_list     ::=  key_datum ("," key_datum)* [","]
key_datum          ::=  expression ":" expression | "**" or_expr
dict_comprehension ::=  expression ":" expression comp_for

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

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

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

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

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

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

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

6.2.8. Выражения генератора

Выражение генератора - это компактное обозначение генератора в круглых скобках:

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 выражения, оно называется asynchronous generator expression. Выражение асинхронного генератора возвращает новый объект асинхронного генератора, который является асинхронным итератором (см. Асинхронные итераторы).

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

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

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

6.2.9. Выражения доходности

yield_atom       ::=  "(" yield_expression ")"
yield_expression ::=  "yield" [expression_list | "from" expression]

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

def gen():  # defines a generator function
    yield 123

async def agen(): # defines an asynchronous generator function
    yield 123

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

Изменено в версии 3.8: Выражения Yield запрещены в неявно вложенных диапазонах, используемых для реализации пониманий и генераторных выражений.

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

Когда вызывается функция генератора, она возвращает итератор, называемый генератором. Этот генератор затем управляет выполнением функции генератора. Выполнение начинается, когда вызывается один из методов генератора. В это время выполнение переходит к первому выражению yield, где оно снова приостанавливается, возвращая значение expression_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 - Простые генераторы

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

PEP 342 - Корутины через расширенные генераторы

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

PEP 380 - Синтаксис для делегирования полномочий субгенератору

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

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

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

6.2.9.1. Генераторно-итераторные методы

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

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

generator.__next__()

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

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

generator.send(value)

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

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

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

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

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

generator.close()

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

6.2.9.2. Примеры

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

>>> 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: Синтаксис для делегирования полномочий субгенератору в разделе «Что нового в Python».

6.2.9.3. Функции асинхронного генератора

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

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

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

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

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

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

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

6.2.9.4. Асинхронные методы генератора-итератора

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

coroutine agen.__anext__()

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

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

coroutine agen.asend(value)

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

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

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

coroutine agen.aclose()

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

6.3. Праймериз

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

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

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

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

attributeref ::=  primary "." identifier

Первичная оценка должна привести к объекту типа, который поддерживает ссылки на атрибуты, что делает большинство объектов. Затем этот объект просят произвести атрибут, имя которого является идентификатором. Это производство может быть настроено путем переопределения метода __getattr__(). Если этот атрибут недоступен, возникает исключение AttributeError. В противном случае тип и значение производимого объекта определяются объектом. Несколько оценок одной и той же ссылки на атрибут могут дать разные объекты.

6.3.2. Подписки

Подписка на экземпляр container class обычно выбирает элемент из контейнера. Подписка на generic class обычно возвращает объект GenericAlias.

subscription ::=  primary "[" expression_list "]"

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

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

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

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

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

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

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

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

6.3.3. Нарезка

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

6.3.4. Звонки

Вызов вызывает вызываемый объект (например, function) с возможно пустой серией arguments:

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__()). Все выражения аргументов оцениваются перед попыткой вызова. Синтаксис формальных списков Определения функций приведен в разделе parameter.

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

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

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

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

Если в вызове функции встречается синтаксис *expression, то expression должен оцениваться как iterable. Элементы из этих итераций рассматриваются так, как если бы они были дополнительными позиционными аргументами. Для вызова 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 должен быть оценен в mapping, содержимое которого рассматривается как дополнительные аргументы ключевого слова. Если ключевое слово уже присутствует (как явный аргумент ключевого слова или в результате другой распаковки), то возникает исключение TypeError.

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

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

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

Если это так…

функция, определяемая пользователем:

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

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

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

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

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

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

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

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

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

6.4. Ожидание выражения

Приостанавливает выполнение coroutine на объекте awaitable. Может использоваться только внутри coroutine function.

await_expr ::=  "await" primary

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

6.5. Энергетический оператор

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

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

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

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

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

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

Эта операция может быть настроена с помощью специального метода __pow__().

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

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

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

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

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

Унарный оператор ~ (invert) дает побитовую инверсию своего целочисленного аргумента. Побитовая инверсия 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__().

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

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

Операторы / (деление) и // (поэтажное деление) выдают результат деления своих аргументов. Числовые аргументы сначала преобразуются к общему типу. Деление целых чисел дает float, а деление целых чисел на пол дает целое число; в результате получается математическое деление с применением функции „floor“ к результату. Деление на ноль вызывает исключение ZeroDivisionError.

Эта операция может быть настроена с помощью специальных методов __truediv__() и __floordiv__().

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

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

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

Операцию modulo можно настроить с помощью специального метода __mod__().

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

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

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

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

Эта операция может быть настроена с помощью специального метода __sub__().

6.8. Сменная работа

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

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

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

Эта операция может быть настроена с помощью специальных методов __lshift__() и __rshift__().

Сдвиг вправо на 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 (исключающее OR) своих аргументов, которые должны быть целыми числами или один из них должен быть пользовательским объектом, переопределяющим специальные методы __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. Пользовательские rich comparison methods могут возвращать небулевы значения. В этом случае 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. Типы могут настраивать свое поведение сравнения, реализуя rich comparison methods подобно __lt__(), описанному в Базовая настройка.

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

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

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

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

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

    При сравнении порядков (<, >, <= и >=) возникает ошибка 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 не обеспечивает соблюдение этих правил согласованности. Фактически, значения not-a-number являются примером несоблюдения этих правил.

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, если при итерации по z выдается некоторое значение x is z or x == z, для которого выражение y истинно. Если во время итерации возникает исключение, то это будет выглядеть так, как если бы 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: False, None, числовой ноль всех типов, а также пустые строки и контейнеры (включая строки, кортежи, списки, словари, множества и замороженные множества). Все остальные значения интерпретируются как true. Определяемые пользователем объекты могут настраивать свое истинностное значение, предоставляя метод __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)

Добавлено в версии 3.8: Более подробную информацию о выражениях присваивания смотрите в PEP 572.

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

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. Лямбды

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

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

def <lambda>(parameters):
    return expression

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

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

expression_list    ::=  expression ("," expression)* [","]
starred_list       ::=  starred_item ("," starred_item)* [","]
starred_expression ::=  expression | (starred_item ",")* [starred_item]
starred_item       ::=  assignment_expression | "*" or_expr

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

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

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

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

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

Ожидание выражения

**

Экспоненция 5

+x, -x, ~x

Положительный, отрицательный, побитовый НЕ

*, @, /, //, %

Умножение, матричное умножение, деление, половинное деление, остаток 6

+, -

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

<<, >>

Смены

&

Побитовое И

^

Побитовый XOR

|

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

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

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

not x

Булево НЕ

and

Булево И

or

Булево ИЛИ

ifelse

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

lambda

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

:=

Выражение назначения

Сноски

1

Хотя abs(x%y) < abs(y) верно математически, для плавающих чисел оно может быть неверно численно из-за округления. Например, если предположить, что на платформе Python поплавок является числом двойной точности IEEE 754, то для того, чтобы -1e-100 % 1e100 имел тот же знак, что и 1e100, вычисленный результат будет -1e-100 + 1e100, который численно точно равен 1e100. Функция math.fmod() возвращает результат, знак которого совпадает со знаком первого аргумента, и поэтому в данном случае возвращает -1e-100. Какой подход является более подходящим, зависит от конкретного приложения.

2

Если x очень близко к точному целому числу, кратному y, то возможно, что x//y будет на единицу больше, чем (x-x%y)//y из-за округления. В таких случаях Python возвращает последний результат, чтобы сохранить, что divmod(x,y)[0] * y + x % y очень близко к x.

3

Стандарт Unicode различает code points (например, U+0041) и abstract characters (например, «LATIN CAPITAL LETTER A»). Хотя большинство абстрактных символов в Юникоде представлены только с помощью одной кодовой точки, существует ряд абстрактных символов, которые могут быть представлены с помощью последовательности из более чем одной кодовой точки. Например, абстрактный символ «LATIN CAPITAL LETTER C WITH CEDILLA» может быть представлен как один precomposed character в кодовой позиции U+00C7, или как последовательность base character в кодовой позиции U+0043 (LATIN CAPITAL LETTER C), за которой следует combining character в кодовой позиции U+0327 (COMBINING CEDILLA).

Операторы сравнения строк сравнивают на уровне кодовых точек Unicode. Это может быть неинтуитивно понятным для человека. Например, "\u00C7" == "\u0043\u0327" равно False, хотя обе строки представляют один и тот же абстрактный символ «LATIN CAPITAL LETTER C WITH CEDILLA».

Чтобы сравнить строки на уровне абстрактных символов (то есть интуитивно понятным для человека способом), используйте unicodedata.normalize().

4

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

5

Оператор мощности ** связывается менее плотно, чем арифметический или побитовый унарный оператор справа от него, то есть 2**-1 является 0.5.

6

Оператор % также используется для форматирования строк; применяется тот же приоритет.

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