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
.
** Искажение личных имен:** Когда идентификатор, который текстуально встречается в определении класса, начинается с двух или более символов подчеркивания и не заканчивается двумя или более символами подчеркивания, он считается private name этого класса. Личные имена преобразуются в более длинную форму до того, как для них будет сгенерирован код. В результате преобразования имя класса будет вставлено без начального подчеркивания и с одним символом подчеркивания перед именем. Например, идентификатор __spam
, встречающийся в классе с именем Ham
, будет преобразован в _Ham__spam
. Это преобразование не зависит от синтаксического контекста, в котором используется идентификатор. Если преобразованное имя слишком длинное (более 255 символов), может произойти усечение, определяемое реализацией. Если имя класса состоит только из символов подчеркивания, преобразование не выполняется.
6.2.2. Литералы¶
Python поддерживает строковые и байтовые литералы, а также различные числовые литералы:
literal ::=stringliteral
|bytesliteral
|integer
|floatnumber
|imagnumber
Вычисление литерала приводит к получению объекта заданного типа (строка, байт, целое число, число с плавающей запятой, комплексное число) с заданным значением. Значение может быть приблизительным в случае литералов с плавающей запятой и мнимых (комплексных) литералов. Более подробную информацию смотрите в разделе Литералы.
Все литералы соответствуют неизменяемым типам данных, и, следовательно, идентичность объекта менее важна, чем его значение. При многократной обработке литералов с одинаковым значением (либо с одинаковым вхождением в текст программы, либо с другим вхождением) может быть получен один и тот же объект или другой объект с одинаковым значением.
6.2.3. Формы, заключенные в круглые скобки¶
Заключенная в круглые скобки форма - это необязательный список выражений, заключенный в круглые скобки:
parenth_form ::= "(" [starred_expression
] ")"
Список выражений, заключенный в круглые скобки, дает все, что дает этот список выражений: если список содержит хотя бы одну запятую, он дает кортеж; в противном случае он дает единственное выражение, составляющее список выражений.
Пустая пара круглых скобок приводит к появлению пустого объекта tuple. Поскольку кортежи неизменяемы, применяются те же правила, что и для литералов (т.е. два вхождения пустого кортежа могут приводить к одному и тому же объекту, а могут и не приводить).
Обратите внимание, что кортежи формируются не с помощью круглых скобок, а с помощью запятой. Исключением является пустой кортеж, для которого требуются круглые скобки — использование «nothing» без скобок в выражениях приведет к неоднозначностям и позволит обычным опечаткам проходить незамеченными.
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. Асинхронное понимание может приостановить выполнение сопрограммы, в которой оно появляется. Смотрите также PEP 530.
Добавлено в версии 3.6: Было введено асинхронное понимание.
Изменено в версии 3.8: yield
и yield from
запрещены в неявно вложенной области видимости.
Изменено в версии 3.11: Асинхронное понимание теперь разрешено внутри приложений в асинхронных функциях. Внешние приложения неявно становятся асинхронными.
6.2.5. Отображение списка¶
Отображение списка - это, возможно, пустая последовательность выражений, заключенных в квадратные скобки:
list_display ::= "[" [starred_list
|comprehension
] "]"
Отображение списка приводит к появлению нового объекта list, содержимое которого определяется либо списком выражений, либо понятием. Когда предоставляется список выражений, разделенный запятыми, его элементы вычисляются слева направо и помещаются в объект list в указанном порядке. Когда предоставляется понимание, список составляется из элементов, полученных в результате понимания.
6.2.6. Установите дисплеи¶
Отображение набора обозначается фигурными скобками и отличается от отображения словаря отсутствием двоеточий, разделяющих ключи и значения:
set_display ::= "{" (starred_list
|comprehension
) "}"
Отображение set приводит к появлению нового изменяемого объекта set, содержимое которого определяется либо последовательностью выражений, либо пониманием. Когда предоставляется список выражений, разделенных запятыми, его элементы оцениваются слева направо и добавляются к объекту set. Когда дается понимание, набор строится из элементов, полученных в результате понимания.
Пустой набор не может быть создан с помощью {}
; этот литерал создает пустой словарь.
6.2.7. Отображение словаря¶
Отображение словаря - это, возможно, пустой набор элементов dict (пар ключ/значение), заключенных в фигурные скобки:
dict_display ::= "{" [dict_item_list
|dict_comprehension
] "}" dict_item_list ::=dict_item
(","dict_item
)* [","] dict_item ::=expression
":"expression
| "**"or_expr
dict_comprehension ::=expression
":"expression
comp_for
При отображении словаря отображается новый объект словаря.
Если задана последовательность элементов dict, разделенных запятыми, они вычисляются слева направо для определения записей словаря: каждый ключевой объект используется в качестве ключа в словаре для хранения соответствующего значения. Это означает, что вы можете указать один и тот же ключ несколько раз в списке элементов dict, и конечное значение словаря для этого ключа будет последним заданным значением.
Двойная звездочка **
обозначает dictionary unpacking. Его операндом должен быть mapping. Каждый элемент отображения добавляется в новый словарь. Более поздние значения заменяют значения, уже заданные более ранними элементами dict и более ранними распаковками словаря.
Добавлено в версии 3.5: Распаковка в словарные дисплеи, первоначально предложенные PEP 448.
Для понимания dict, в отличие от понимания list и set, требуются два выражения, разделенные двоеточием, за которыми следуют обычные предложения «for» и «if». Когда выполняется понимание, результирующие элементы key и value вставляются в новый словарь в том порядке, в котором они были созданы.
Ограничения на типы значений ключа перечислены ранее в разделе Иерархия стандартных типов. (Подводя итог, тип ключа должен быть hashable, что исключает все изменяемые объекты.) Конфликты между дублирующимися ключами не обнаружены; преобладает последнее значение (текстуально самое правое на дисплее), сохраненное для данного значения ключа.
Изменено в версии 3.8: До выхода Python 3.8 в dict-версиях порядок вычисления ключа и значения не был четко определен. В CPython значение вычислялось перед ключом. Начиная с версии 3.8, ключ вычисляется перед значением, как предложено в PEP 572.
6.2.8. Генераторные выражения¶
Генераторное выражение - это компактная генераторная запись в круглых скобках:
generator_expression ::= "("expression
comp_for
")"
Генерирующее выражение приводит к созданию нового генерирующего объекта. Его синтаксис такой же, как и у comprehensions, за исключением того, что оно заключено в круглые скобки, а не в фигурные скобки.
Переменные, используемые в генераторном выражении, вычисляются лениво, когда для объекта generator вызывается метод __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_from ::= "yield" "from"expression
yield_expression ::= "yield"expression_list
|yield_from
Выражение 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: Выводить выражения, запрещенные в неявно вложенных областях, используемых для реализации интерпретаций и генераторных выражений.
Функции генератора описаны ниже, в то время как функции асинхронного генератора описаны отдельно в разделе Функции асинхронного генератора.
Когда вызывается функция-генератор, она возвращает итератор, известный как generator. Этот генератор затем управляет выполнением функции-генератора. Выполнение начинается при вызове одного из методов генератора. В это время выполнение переходит к первому выражению yield, где оно снова приостанавливается, возвращая вызывающему генератору значение expression_list
или None
, если 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(value)¶
- generator.throw(type[, value[, traceback]])
Генерирует исключение в том месте, где генератор был приостановлен, и возвращает следующее значение, полученное функцией генератора. Если генератор завершает работу, не выдав другого значения, генерируется исключение
StopIteration
. Если функция-генератор не перехватывает переданное исключение или генерирует другое исключение, то это исключение передается вызывающей стороне.При обычном использовании это вызывается с помощью единственного экземпляра exception аналогично тому, как используется ключевое слово
raise
.Однако для обеспечения обратной совместимости поддерживается вторая сигнатура, в соответствии с соглашением, принятым в более старых версиях Python. Аргумент type должен быть классом exception, а value - экземпляром exception. Если 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
в функции сопрограммы аналогично тому, как объект генератора использовался бы в инструкции for
.
Вызов одного из методов асинхронного генератора возвращает объект awaitable, и выполнение начинается, когда этот объект находится в режиме ожидания. В это время выполнение переходит к первому выражению yield, где оно снова приостанавливается, возвращая значение expression_list
ожидающей сопрограмме. Как и в случае с генератором, приостановка означает, что сохраняется все локальное состояние, включая текущие привязки локальных переменных, указатель команды, стек внутренней оценки и состояние обработки любых исключений. Когда выполнение возобновляется путем ожидания следующего объекта, возвращаемого методами асинхронного генератора, функция может работать точно так же, как если бы выражение yield было просто еще одним внешним вызовом. Значение выражения yield после возобновления зависит от метода, который возобновил выполнение. Если используется __anext__()
, то результатом будет None
. В противном случае, если используется asend()
, то результатом будет значение, переданное в этот метод.
Если асинхронный генератор завершает работу раньше времени из-за break
, отмены вызывающей задачи или других исключений, код асинхронной очистки генератора будет запущен и, возможно, вызовет исключения или обратится к контекстным переменным в неожиданном контексте - возможно, по истечении срока действия задач, от которого это зависит, или во время выполнения асинхронной задачи. завершение цикла обработки событий при вызове функции сбора мусора асинхронного генератора. Чтобы предотвратить это, вызывающий должен явно закрыть асинхронный генератор, вызвав метод aclose()
, чтобы завершить работу генератора и в конечном итоге отключить его от цикла обработки событий.
В функции асинхронного генератора выражения yield допускаются в любом месте конструкции try
. Однако, если асинхронный генератор не возобновляется до его завершения (при достижении нулевого количества ссылок или при сборке мусора), то выражение yield в конструкции try
может привести к сбою в выполнении ожидающих выполнения предложений finally
. В этом случае цикл обработки событий или планировщик, запускающий асинхронный генератор, отвечает за вызов метода асинхронного генератора-итератора aclose()
и запуск результирующего объекта сопрограммы, что позволяет выполнять любые ожидающие выполнения предложения finally
.
Чтобы позаботиться о завершении после завершения цикла обработки событий, цикл обработки событий должен определить функцию finalizer, которая принимает асинхронный генератор-итератор и, предположительно, вызывает aclose()
и выполняет сопрограмму. Этот финализатор можно зарегистрировать, вызвав sys.set_asyncgen_hooks()
. При первом повторении асинхронный генератор-итератор сохранит зарегистрированный финализатор, который будет вызван при завершении. Для получения справочного примера метода finalizer смотрите реализацию asyncio.Loop.shutdown_asyncgens
в Lib/asyncio/base_events.py.
Выражение yield from <expr>
является синтаксической ошибкой при использовании в функции асинхронного генератора.
6.2.9.4. Методы асинхронного генератора-итератора¶
В этом подразделе описываются методы итератора асинхронного генератора, которые используются для управления выполнением функции генератора.
- coroutine agen.__anext__()¶
Возвращает ожидаемое значение, которое при запуске запускает асинхронный генератор или возобновляет его при последнем выполненном выражении 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(value)¶
- coroutine agen.athrow(type[, value[, traceback]])
Возвращает ожидаемое значение, которое вызывает исключение типа
type
в точке, где асинхронный генератор был приостановлен, и возвращает следующее значение, полученное функцией генератора, как значение возникшего исключенияStopIteration
. Если асинхронный генератор завершает работу, не выдавая другого значения, то в системе available возникает исключениеStopAsyncIteration
. Если функция-генератор не перехватывает переданное исключение или генерирует другое исключение, то при запуске ожидаемого исключения это исключение передается вызывающей стороне ожидаемого исключения.
- coroutine agen.aclose()¶
Возвращает ожидаемое значение, которое при запуске выдаст
GeneratorExit
в функцию асинхронного генератора в точке, где она была приостановлена. Если функция асинхронного генератора затем завершает работу корректно, уже закрыта или вызываетGeneratorExit
(не перехватывая исключение), то возвращаемое ожидаемое значение вызовет исключениеStopIteration
. Любые другие ожидаемые значения, возвращаемые последующими вызовами асинхронного генератора, вызовут исключениеStopAsyncIteration
. Если асинхронный генератор выдает значение, ожидаемое значение генерируется какRuntimeError
. Если асинхронный генератор генерирует какое-либо другое исключение, оно передается вызывающему объекту из доступных. Если асинхронный генератор уже завершал работу из-за исключения или обычного завершения, то дальнейшие вызовыaclose()
вернут ожидаемое значение, которое ничего не делает.
6.3. Первичный¶
Основные символы представляют собой наиболее тесно связанные операции языка. Их синтаксис следующий:
primary ::=atom
|attributeref
|subscription
|slicing
|call
6.3.1. Ссылки на атрибуты¶
Ссылка на атрибут является основной, за которой следуют точка и имя:
attributeref ::=primary
"."identifier
Первичный объект должен быть преобразован в объект типа, который поддерживает ссылки на атрибуты, что и делает большинство объектов. Затем этот объект запрашивается для создания атрибута, имя которого является идентификатором. Тип и значение, которые генерируются, определяются объектом. Многократные вычисления одной и той же ссылки на атрибут могут привести к получению разных объектов.
Это производство можно настроить, переопределив метод __getattribute__()
или метод __getattr__()
. Сначала вызывается метод __getattribute__()
, который либо возвращает значение, либо вызывает AttributeError
, если атрибут недоступен.
Если задано значение AttributeError
и объект имеет метод __getattr__()
, этот метод вызывается в качестве резервного.
6.3.2. Подписки¶
Подписка на экземпляр container class обычно приводит к выбору элемента из контейнера. Подписка на generic class обычно возвращает объект GenericAlias.
subscription ::=primary
"["expression_list
"]"
Когда объект подписан, интерпретатор вычисляет первичный объект и список выражений.
Первичный объект должен соответствовать объекту, поддерживающему подписку. Объект может поддерживать подписку путем определения одного или обоих из __getitem__()
и __class_getitem__()
. Когда первичное значение подписано, результат вычисления списка выражений будет передан одному из этих методов. Более подробную информацию о том, когда вместо __getitem__
вызывается __class_getitem__
, смотрите в разделе __класс_getitem__ против __getitem__.
Если список выражений содержит хотя бы одну запятую, он будет равен tuple
, содержащему элементы списка выражений. В противном случае список выражений будет равен значению единственного элемента списка.
Для встроенных объектов существует два типа объектов, которые поддерживают подписку через __getitem__()
:
Сопоставления. Если первичным является mapping, список выражений должен вычислять объект, значение которого является одним из ключей сопоставления, и подписка выбирает значение в сопоставлении, соответствующее этому ключу. Примером встроенного класса отображения является класс
dict
.Последовательности. Если первичным является 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__()
, что и обычная подписка) с помощью ключа, который создается из списка фрагментов следующим образом. Если список фрагментов содержит хотя бы одну запятую, ключом является кортеж, содержащий преобразование элементов фрагмента; в противном случае ключом является преобразование отдельного элемента фрагмента. Преобразование элемента фрагмента, который является выражением, является этим выражением. Преобразованием соответствующего фрагмента является объект slice (см. раздел Иерархия стандартных типов), атрибуты которого start
, stop
и step
являются значениями выражений, заданных в виде нижней границы, верхней границы и шаг, соответственно, заменяя пропущенные выражения 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: Реализация может предоставлять встроенные функции, позиционные параметры которых не имеют имен, даже если они «названы» для целей документации, и которые, следовательно, не могут быть заданы с помощью ключевого слова. В 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
.
Когда используется **expression
, каждый ключ в этом сопоставлении должен быть строкой. Каждое значение из сопоставления присваивается первому формальному параметру, подходящему для присвоения ключевого слова, имя которого равно ключу. Ключ не обязательно должен быть идентификатором Python (например, "max-temp °F"
допустимо, хотя он не будет соответствовать ни одному формальному параметру, который можно было бы объявить). Если нет совпадения с формальным параметром, пара ключ-значение собирается с помощью параметра **
, если он есть, или если его нет, генерируется исключение 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 и выдается результат с плавающей точкой. Например, 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__()
.
Унарный оператор +
(plus) возвращает свой числовой аргумент без изменений; операция может быть переопределена с помощью специального метода __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.
Операторы /
(деление) и //
(деление по этажам) возвращают частное от их аргументов. Числовые аргументы сначала преобразуются в общий тип. При делении целых чисел получается число с плавающей точкой, в то время как при делении чисел по полу получается целое число; результатом является математическое деление с применением к результату функции «floor». При делении на ноль возникает исключение ZeroDivisionError
.
Эту операцию можно настроить с помощью специальных методов __truediv__()
и __floordiv__()
.
Оператор %
(по модулю) возвращает остаток от деления первого аргумента на второй. Числовые аргументы сначала преобразуются в общий тип. Аргумент с нулевым значением справа вызывает исключение ZeroDivisionError
. Аргументами могут быть числа с плавающей запятой, например, 3.14%0.7
равно 0.34
(поскольку 3.14
равно 4*0.7 + 0.34
). Оператор вычисления по модулю всегда выдает результат с тем же знаком, что и его второй операнд (или ноль); абсолютное значение результата строго меньше абсолютного значения второго операнда [1].
Операторы разделения по этажам и по модулю связаны следующим образом: x == (x//y)*y + (x%y)
. Разделение по этажам и по модулю также связаны с помощью встроенной функции divmod()
: divmod(x, y) == (x//y, x%y)
. [2].
В дополнение к выполнению операции над числами по модулю, оператор %
также перегружен строковыми объектами для выполнения форматирования строк в старом стиле (также известного как интерполяция). Синтаксис для форматирования строк описан в Справочнике по библиотеке Python, раздел printf -стиль форматирования строки.
Операция по модулю может быть настроена с помощью специального метода __mod__()
.
Оператор деления на число с плавающей запятой, оператор вычисления по модулю и функция 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 своих аргументов, которые должны быть целыми числами или один из них должен быть пользовательским объектом, переопределяющим специальные методы __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
все значения false, аx != x
- true. Такое поведение соответствует стандарту IEEE 754.None
иNotImplemented
являются синглтонами. PEP 8 советует, чтобы сравнения для синглтонов всегда выполнялись с помощьюis
илиis not
, а не операторов равенства.Двоичные последовательности (экземпляры
bytes
илиbytearray
) можно сравнивать как внутри, так и между их типами. Они сравниваются лексикографически, используя числовые значения своих элементов.Строки (экземпляры
str
) сравниваются лексикографически с использованием числовых кодовых точек Unicode (результат работы встроенной функцииord()
) их символов. [3]Строки и двоичные последовательности нельзя сравнивать напрямую.
Последовательности (экземпляры
tuple
,list
, илиrange
) можно сравнивать только внутри каждого из их типов, с тем ограничением, что диапазоны не поддерживают сравнение по порядку. Сравнение на равенство между этими типами приводит к неравенству, а упорядоченное сравнение между этими типами приводит к возникновениюTypeError
.Последовательности сравниваются лексикографически, используя сравнение соответствующих элементов. Встроенные контейнеры обычно предполагают, что идентичные объекты равны самим себе. Это позволяет им обходить тесты на равенство для идентичных объектов, чтобы повысить производительность и сохранить их внутренние инварианты.
Лексикографическое сравнение между встроенными коллекциями выполняется следующим образом:
Чтобы две коллекции сравнивались одинаково, они должны быть одного типа, иметь одинаковую длину, и каждая пара соответствующих элементов должна сравниваться одинаково (например,
[1,2] == (1,2)
равно false, потому что тип не совпадает).Коллекции, поддерживающие сравнение по порядку, упорядочиваются так же, как и их первые неравные элементы (например,
[1,2,x] <= [1,2,y]
имеет то же значение, что иx <= y
). Если соответствующий элемент не существует, то сначала упорядочивается более короткая коллекция (например,[1,2] < [1,2,3]
равно true).
Сопоставления (экземпляры
dict
) сравниваются равными тогда и только тогда, когда они имеют равные пары(key, value)
. Сравнение ключей и значений на равенство обеспечивает рефлексивность.Порядок сравнения (
<
,>
,<=
, и>=
) увеличиваютTypeError
.Наборы (экземпляры
set
илиfrozenset
) можно сравнивать как внутри, так и между их типами.Они определяют операторы сравнения порядков для обозначения тестов подмножеств и надмножеств надстроек. Эти отношения не определяют общее упорядочение (например, два набора
{1,2}
и{2,3}
не равны, не являются ни подмножествами друг друга, ни надмножествами друг друга). Соответственно, наборы не являются подходящими аргументами для функций, которые зависят от общего упорядочения (например,,min()
,max()
, иsorted()
дают неопределенные результаты, учитывая список наборов в качестве входных данных).Сравнение множеств усиливает рефлексивность их элементов.
В большинстве других встроенных типов не реализованы методы сравнения, поэтому они наследуют поведение сравнения по умолчанию.
Определяемые пользователем классы, которые настраивают свое поведение при сравнении, должны, по возможности, следовать некоторым правилам согласованности:
Сравнение на равенство должно быть рефлексивным. Другими словами, идентичные объекты должны сравниваться одинаково:
x is y
подразумеваетx == y
Сравнение должно быть симметричным. Другими словами, следующие выражения должны иметь одинаковый результат:
x == y
иy == x
x != y
иy != x
x < y
иy > x
x <= y
иy >= x
Сравнение должно быть переходным. Следующие (не исчерпывающие) примеры иллюстрируют, что:
x > y and y > z
подразумеваетx > z
x < y and y <= z
подразумеваетx < z
Обратное сравнение должно привести к логическому отрицанию. Другими словами, следующие выражения должны иметь одинаковый результат:
x == y
иnot x != y
x < y
иnot x >= y
(для общего заказа)x > y
иnot x <= y
(для общего заказа)Последние два выражения применимы к полностью упорядоченным коллекциям (например, к последовательностям, но не к наборам или отображениям). Смотрите также
total_ordering()
декоратор.Результат
hash()
должен соответствовать равенству. Объекты, которые равны, должны либо иметь одинаковое хэш-значение, либо быть помечены как недоступные для хэширования.
Python не применяет эти правила согласованности. На самом деле, значения, не являющиеся числами, являются примером несоблюдения этих правил.
6.10.2. Операции по проверке членства¶
Операторы in
и not in
проверяют принадлежность. x in s
вычисляется как True
, если x является членом s, и False
в противном случае. x not in s
возвращает значение, отрицающее значение x in s
. Все встроенные последовательности и типы наборов поддерживают это, а также dictionary, для которого in
проверяет, имеет ли словарь заданный ключ. Для таких типов контейнеров, как list, tuple, set, frozenset, dict или collections.например, выражение x in y
эквивалентно any(x is e or x == e for e in y)
.
Для типов string и bytes x in y
равно True
тогда и только тогда, когда x является подстрокой из y. Эквивалентным тестом является y.find(x) != -1
. Пустые строки всегда считаются подстрокой любой другой строки, поэтому "" in "abc"
вернет True
.
Для пользовательских классов, которые определяют метод __contains__()
, x in y
возвращает True
, если y.__contains__(x)
возвращает истинное значение, и False
в противном случае.
Для пользовательских классов, которые не определяют __contains__()
, но определяют __iter__()
, x in y
равно True
, если некоторое значение 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, False
в противном случае.
Выражение x and y
сначала вычисляет значение x; если значение x равно false, возвращается его значение; в противном случае вычисляется значение y и возвращается результирующее значение.
Выражение x or y
сначала вычисляет значение x; если значение x равно true, возвращается его значение; в противном случае вычисляется значение 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)
Выражения присваивания должны быть заключены в круглые скобки при использовании в качестве операторов expression и при использовании в качестве подвыражений в разделительных, условных, лямбда-выражениях, выражениях с ключевым словом-аргументом и понятием if, а также в операторах assert
, with
, и assignment
. Во всех других местах, где они могут использоваться, круглые скобки не требуются, в том числе в операторах if
и while
.
Добавлено в версии 3.8: Смотрите PEP 572 для получения более подробной информации о выражениях присваивания.
6.13. Условные выражения¶
conditional_expression ::=or_test
["if"or_test
"else"expression
] expression ::=conditional_expression
|lambda_expr
Условные выражения (иногда называемые «тернарным оператором») имеют самый низкий приоритет из всех операций Python.
Выражение x if C else y
сначала вычисляет условие C, а не x. Если значение C равно true, вычисляется значение 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.
Конечная запятая требуется только для создания кортежа из одного элемента, такого как 1,
; во всех остальных случаях она необязательна. Одно выражение без конечной запятой не создает кортеж, а возвращает значение этого выражения. (Чтобы создать пустой кортеж, используйте пустые круглые скобки: ()
.)
6.16. Порядок оценки¶
Python вычисляет выражения слева направо. Обратите внимание, что при вычислении присваивания правая часть вычисляется раньше левой.
В следующих строках выражения будут вычисляться в арифметическом порядке их суффиксов:
expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2
6.17. Приоритет оператора¶
В следующей таблице приведена краткая информация о приоритете операторов в Python, от наивысшего приоритета (наибольшая привязка) до наименьшего приоритета (наименьшая привязка). Операторы в одном и том же поле имеют одинаковый приоритет. Если синтаксис не указан явно, операторы являются двоичными. Операторы в одном и том же поле группируются слева направо (за исключением возведения в степень и условных выражений, которые группируются справа налево).
Обратите внимание, что сравнения, тесты на принадлежность и идентификационные тесты имеют одинаковый приоритет и имеют функцию цепочки слева направо, как описано в разделе Сравнения.
Оператор |
Описание |
---|---|
|
Привязка или выражение в круглых скобках, отображение списка, отображение словаря, отображение набора |
|
Подписка, нарезка, вызов, ссылка на атрибут |
Ожидающее выражение |
|
|
Возведение в степень [5] |
|
Положительный, отрицательный, побитовый НЕ |
|
Умножение, матричное умножение, деление, минимальное деление, остаток [6] |
|
Сложение и вычитание |
|
Сдвиги |
|
Побитовое И |
|
Побитовое исключающее значение |
|
Побитовый ИЛИ |
Сравнения, включая тесты на членство и идентификационные тесты |
|
Логическое значение НЕ |
|
Логическое И |
|
Логическое ЗНАЧЕНИЕ ИЛИ |
|
|
Условное выражение |
Лямбда-выражение |
|
|
Выражение присваивания |
Сноски