6. Выражения

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

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

Искажение приватного имени:: когда идентификатор, который текстуально встречается в определении класса, начинается с двух или более символов подчеркивания и не заканчивается двумя или более символами подчеркивания, он считается приватным именем этого класса. Частные имена преобразуются в более длинную форму до того, как для них будет сгенерирован код. Преобразование вставляет имя класса с удалением начальных подчеркиваний и вставкой одного подчеркивания перед именем. Например, идентификатор __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" expression_nocond [comp_iter]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6.2.9. Выражение Yield

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

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

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

async def agen(): # определяет функцию асинхронного генератора
    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 и синтаксису генераторов, делающее их пригодными для использования в качестве простых корутин.
PEP 380 - Синтаксис для делегирования подгенератору
Предложение ввести синтаксис yield_from, упрощающий делегирование субгенераторам.
PEP 525 - Асинхронные генераторы
Предложение, которое расширило PEP 492, добавив возможности генератора к функциям корутин.

6.2.9.1. Методы генератора-итератора

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

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

generator.__next__()

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

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

generator.send(value)

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

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

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

generator.close()

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

6.2.9.2. Примеры

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

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

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

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

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

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

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

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

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

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

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

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

coroutine agen.__anext__()

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

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

coroutine agen.asend(value)

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

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

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

coroutine agen.aclose()

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

6.3. Праймериз

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

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

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

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

attributeref ::=  primary "." identifier

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

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

Инексирование выбирает элемент последовательности (строка, кортеж или список) или объекта отображения (словаря) :

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

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

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

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

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

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

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

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 являются значениями выражений, заданными как нижняя граница, верхняя граница и шаг, соответственно, заменяющие None отсутствующими выражениями.

6.3.4. Вызываемые

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

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.

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

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

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

Если это —

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

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

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

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

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

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

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

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

сущность класса:

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

6.4. Await выражения

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

await_expr ::=  "await" primary

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

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

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

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

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

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

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

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

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

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

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

Унарный оператор - (минус) возвращает отрицание его числового аргумента.

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

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

Во всех трех случаях, если аргумент не имеет надлежащего типа, поднимается исключение 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

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

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

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

Операторы / (деление) и // (деление с округлением в меньшую сторону) возвращают частное своих аргументов. Числовые аргументы сначала преобразуются в общий тип. Деление целых чисел дает число с плавающей запятой, в то время как деление целых чисел с округлением возвращает целое число; результатом является математическое деление с применением к результату функции «floor». При делении на ноль возникает исключение ZeroDivisionError.

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

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

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

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

6.8. Здвиговые операции

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

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

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

Сдвиг вправо на 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

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

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

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

6.10. Сравнения

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

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

Сравнения возвращают логические значения True или False.

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

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

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

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

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

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

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

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

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

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

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

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

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

  • None и NotImplemented - синглтоны. PEP 8 советует, что сравнения для одиночных чисел всегда должны выполняться с is или is not, а не с операторами равенства.

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

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

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

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

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

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

    • Чтобы две коллекции сравнивались равными, они должны быть одного типа, иметь одинаковую длину, и каждая пара соответствующих элементов должна сравниваться одинаково (например, [1,2] == (1,2) имеет значение false, поскольку тип не совпадает).
    • Коллекции, поддерживающие сравнение порядка, упорядочиваются так же, как их первые неравные элементы (например, [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 не применяет эти правила согласованности. Фактически, нечисловые значения являются примером несоблюдения этих правил.

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, 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_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
expression_nocond      ::=  or_test | lambda_expr_nocond

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

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

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

6.14. Лямбды

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

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

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

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

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

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

Оператор Описание
:= Выражение присвоения
lambda Лямбда-выражение
ifelse Условное выражение
or Логическое ИЛИ
and Логическое И
not x Логическое НЕ
in, not in, is, is not, <, <=, >, >=, !=, == Сравнения, включая тесты членства и тесты идентичности
\| Побитовое ИЛИ
\^ Побитовое исключающее ИЛИ
& Побитовое И
<<, >> Сдвиги
\+, \- Сложение и вычитание
*, @, /, //, % Умножение, умножение матриц, деление, нижнее деление, остаток [5]
+x, -x, ~x Положительное, отрицательное, побитовое НЕ
** Возведение в степень [6]
await x Await выражения
x[index], x[index:index], x(arguments...), x.attribute Индексация, нарезка, вызов, ссылка на атрибут

(expressions...),

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

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

Сноски

[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]

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

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

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

[4]Из-за автоматической сборки мусора, свободных списков и динамической природы дескрипторов вы можете заметить, казалось бы, необычное поведение при некоторых применениях оператора is, например, при сравнении между методами экземпляра или константами. Проверьте их документацию для получения дополнительной информации.
[5]Оператор % также используется для форматирования строк; применяется тот же приоритет.
[6]Оператор возведения в степень ** связывает менее жестко, чем арифметический или побитовый унарный оператор справа, то есть 2**-1 — это 0.5.