8. Составные утверждения¶
Составные операторы содержат (группы) других операторов; они каким-то образом влияют на выполнение этих других операторов или контролируют его. Как правило, составные операторы занимают несколько строк, хотя в простых вариантах весь составной оператор может содержаться в одной строке.
Операторы if
, while
и for
реализуют традиционные конструкции потока управления. try
определяет обработчики исключений и/или код очистки для группы инструкций, в то время как инструкция with
позволяет выполнять код инициализации и завершения для всего блока кода. Определения функций и классов также являются синтаксически составными инструкциями.
Составной оператор состоит из одного или нескольких «предложений». Предложение состоит из заголовка и «набора». Заголовки предложений конкретного составного оператора имеют одинаковый уровень отступа. Каждый заголовок предложения начинается с уникального ключевого слова и заканчивается двоеточием. Набор - это группа операторов, управляемых предложением. Набор может состоять из одного или нескольких простых операторов, разделенных точкой с запятой, в той же строке, что и заголовок, после двоеточия в заголовке, или из одного или нескольких операторов с отступом в последующих строках. Только последняя форма набора может содержать вложенные составные операторы; следующее является незаконным, главным образом потому, что было бы неясно, к какому предложению if
относится следующее предложение else
:
if test1: if test2: print(x)
Также обратите внимание, что точка с запятой в данном контексте используется более жестко, чем двоеточие, так что в следующем примере выполняются либо все вызовы print()
, либо ни один из них:
if x < y < z: print(x); print(y); print(z)
Подведение:
compound_stmt ::=if_stmt
|while_stmt
|for_stmt
|try_stmt
|with_stmt
|match_stmt
|funcdef
|classdef
|async_with_stmt
|async_for_stmt
|async_funcdef
suite ::=stmt_list
NEWLINE | NEWLINE INDENTstatement
+ DEDENT statement ::=stmt_list
NEWLINE |compound_stmt
stmt_list ::=simple_stmt
(";"simple_stmt
)* [";"]
Обратите внимание, что операторы всегда заканчиваются на NEWLINE
, за которым, возможно, следует DEDENT
. Также обратите внимание, что необязательные предложения продолжения всегда начинаются с ключевого слова, которое не может запускать оператор, таким образом, нет никакой двусмысленности (проблема «зависания else
» решается в Python, требуя, чтобы вложенные операторы if
были с отступом).
При форматировании грамматических правил в следующих разделах каждое предложение вынесено в отдельную строку для большей ясности.
8.1. Оператор if
¶
Оператор if
используется для условного выполнения:
if_stmt ::= "if"assignment_expression
":"suite
("elif"assignment_expression
":"suite
)* ["else" ":"suite
]
Он выбирает точно один из наборов, вычисляя выражения одно за другим, пока одно из них не будет признано истинным (смотрите раздел Булевы операции для определения значений true и false); затем выполняется этот набор (и никакая другая часть инструкции if
выполняется или вычисляется). Если все выражения являются ложными, выполняется набор предложений else
, если он присутствует.
8.2. Оператор while
¶
Оператор while
используется для повторного выполнения до тех пор, пока выражение истинно:
while_stmt ::= "while"assignment_expression
":"suite
["else" ":"suite
]
Это многократно проверяет выражение и, если оно истинно, выполняет первый набор; если выражение ложно (что может быть при первой проверке), выполняется набор из предложения else
, если оно присутствует, и цикл завершается.
Оператор break
, выполненный в первом наборе, завершает цикл, не выполняя набор else
. Оператор continue
, выполненный в первом наборе, пропускает остальную часть набора и возвращается к тестированию выражения.
8.3. Оператор for
¶
Оператор for
используется для перебора элементов последовательности (таких как строка, кортеж или список) или другого повторяемого объекта:
for_stmt ::= "for"target_list
"in"starred_list
":"suite
["else" ":"suite
]
Выражение starred_list
вычисляется один раз; оно должно привести к объекту iterable. Для этой итерируемой переменной создается объект iterator. Затем первый элемент, предоставленный итератором, назначается целевому списку с использованием стандартных правил назначения (см. Операторы присваивания), и набор выполняется. Это повторяется для каждого элемента, предоставленного итератором. Когда итератор исчерпан, выполняется набор в предложении else
, если он присутствует, и цикл завершается.
Оператор break
, выполненный в первом наборе, завершает цикл, не выполняя набор else
предложения. Оператор continue
, выполняемый в первом наборе, пропускает остальную часть набора и переходит к следующему элементу или к предложению else
, если следующего элемента нет.
Цикл for присваивает значения переменным в целевом списке. При этом перезаписываются все предыдущие присвоения этим переменным, включая те, которые были сделаны в наборе параметров цикла for:
for i in range(10):
print(i)
i = 5 # this will not affect the for-loop
# because i will be overwritten with the next
# index in the range
Имена из целевого списка не удаляются по завершении цикла, но если последовательность пуста, цикл вообще не будет присваивать их. Подсказка: встроенный тип range()
представляет собой неизменяемые арифметические последовательности целых чисел. Например, последовательное повторение range(3)
приводит к 0, 1, а затем к 2.
Изменено в версии 3.11: Отмеченные звездочкой элементы теперь разрешены в списке выражений.
8.4. Оператор try
¶
Оператор try
определяет обработчики исключений и/или код очистки для группы операторов:
try_stmt ::=try1_stmt
|try2_stmt
|try3_stmt
try1_stmt ::= "try" ":"suite
("except" [expression
["as"identifier
]] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try2_stmt ::= "try" ":"suite
("except" "*"expression
["as"identifier
] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try3_stmt ::= "try" ":"suite
"finally" ":"suite
Дополнительную информацию об исключениях можно найти в разделе Исключения, а информацию об использовании инструкции raise
для создания исключений можно найти в разделе Оператор raise.
8.4.1. except
предложение¶
В предложениях except
указывается один или несколько обработчиков исключений. Если в предложении try
не возникает исключения, обработчик исключений не выполняется. Когда в наборе try
возникает исключение, запускается поиск обработчика исключения. Этот поиск поочередно проверяет предложения except
, пока не будет найдено одно, соответствующее исключению. Предложение без выражения except
, если оно присутствует, должно быть последним; оно соответствует любому исключению. Для предложения except
с выражением вычисляется это выражение, и предложение соответствует исключению, если результирующий объект «совместим» с этим исключением. Объект совместим с исключением, если этот объект является классом или non-virtual base class объекта исключения, или кортежем, содержащим элемент, который является классом или невиртуальным базовым классом объекта исключения.
Если ни одно предложение except
не соответствует исключению, поиск обработчика исключений продолжается в окружающем коде и в стеке вызовов. [1]
Если при вычислении выражения в заголовке предложения except
возникает исключение, первоначальный поиск обработчика отменяется и начинается поиск нового исключения в окружающем коде и в стеке вызовов (оно обрабатывается так, как если бы весь try
оператор вызвал исключение).
Когда найдено соответствующее предложение except
, исключение присваивается целевому объекту, указанному после ключевого слова as
в этом предложении except
, если оно присутствует, и выполняется набор предложений except
. Все предложения except
должны содержать исполняемый блок. Когда достигается конец этого блока, выполнение продолжается в обычном режиме после выполнения всего оператора try
. (Это означает, что если для одного и того же исключения существуют два вложенных обработчика и исключение возникает в предложении try
внутреннего обработчика, внешний обработчик не будет обрабатывать это исключение.)
Если исключение было задано с помощью as target
, оно удаляется в конце предложения except
. Это как если бы
except E as N:
foo
был переведен на
except E as N:
try:
foo
finally:
del N
Это означает, что исключению должно быть присвоено другое имя, чтобы на него можно было ссылаться после предложения except
. Исключения удаляются, потому что с присоединенной к ним обратной трассировкой они образуют ссылочный цикл с фреймом стека, сохраняя все локальные объекты в этом фрейме активными до тех пор, пока не произойдет следующая сборка мусора.
Перед выполнением набора предложений except
исключение сохраняется в модуле sys
, где к нему можно получить доступ из тела предложения except
, вызвав sys.exception()
. При выходе из обработчика исключений исключение, сохраненное в модуле sys
, возвращается к своему предыдущему значению:
>>> print(sys.exception())
None
>>> try:
... raise TypeError
... except:
... print(repr(sys.exception()))
... try:
... raise ValueError
... except:
... print(repr(sys.exception()))
... print(repr(sys.exception()))
...
TypeError()
ValueError()
TypeError()
>>> print(sys.exception())
None
8.4.2. except*
предложение¶
Предложения except*
используются для обработки ExceptionGroup
s. Тип исключения для сопоставления интерпретируется как в случае except
, но в случае групп исключений мы можем получить частичные совпадения, когда тип совпадает с некоторыми исключениями в группе. Это означает, что может выполняться несколько предложений except*
, каждое из которых обрабатывает часть группы исключений. Каждое предложение выполняется не более одного раза и обрабатывает группу исключений, состоящую из всех совпадающих исключений. Каждое исключение в группе обрабатывается не более чем одним предложением except*
, первым, которое ему соответствует.
>>> try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| ExceptionGroup: eg
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
Все оставшиеся исключения, которые не были обработаны ни одним из предложений except*
, повторно вызываются в конце и объединяются в группу исключений вместе со всеми исключениями, которые были вызваны из предложений except*
.
Начиная с версии 3.11.4, когда обрабатывается весь ExceptionGroup
и из предложения except*
возникает только одно исключение, это исключение больше не преобразуется в новое ExceptionGroup
.
Если возникшее исключение не является группой исключений и его тип соответствует одному из предложений except*
, оно перехватывается и завершается группой исключений с пустой строкой сообщения.
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError()))
Предложение except*
должно иметь соответствующий тип, и этот тип не может быть подклассом BaseExceptionGroup
. Невозможно смешивать except
и except*
в одном и том же предложении try
. break
, continue
и return
не могут появляться в предложении except*
.
8.4.3. else
предложение¶
Необязательное предложение else
выполняется, если поток управления покидает набор try
, исключение не было вызвано и return
, continue
, или break
заявление было казнен. Исключения в предложении else
не обрабатываются предыдущими предложениями except
.
8.4.4. finally
предложение¶
Если finally
присутствует, это указывает на обработчик «очистки». Выполняется предложение try
, включая любые предложения except
и else
. Если в каком-либо из предложений возникает исключение и оно не обрабатывается, оно временно сохраняется. Выполняется предложение finally
. Если есть сохраненное исключение, оно повторно вызывается в конце предложения finally
. Если предложение finally
вызывает другое исключение, сохраненное исключение устанавливается в качестве контекста нового исключения. Если в предложении finally
выполняется оператор return
, break
или continue
, сохраненное исключение отбрасывается:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
Информация об исключении недоступна программе во время выполнения предложения finally
.
Когда оператор return
, break
или continue
выполняется в наборе try
оператора try
…finally
, предложение finally
также выполняется «на выходе».
Возвращаемое функцией значение определяется последним выполненным оператором return
. Поскольку предложение finally
выполняется всегда, оператор return
, выполняемый в предложении finally
, всегда будет выполняться последним:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
Изменено в версии 3.8: До выхода Python 3.8 оператор continue
был недопустим в предложении finally
из-за проблемы с реализацией.
8.5. Оператор with
¶
Оператор with
используется для завершения выполнения блока методами, определенными контекстным менеджером (см. раздел С помощью контекстных менеджеров заявлений). Это позволяет инкапсулировать общие шаблоны использования try
…except
…finally
для удобства повторного использования.
with_stmt ::= "with" ( "("with_stmt_contents
","? ")" |with_stmt_contents
) ":"suite
with_stmt_contents ::=with_item
(","with_item
)* with_item ::=expression
["as"target
]
Выполнение инструкции with
с одним «item» выполняется следующим образом:
Выражение контекста (выражение, указанное в
with_item
) вычисляется для получения менеджера контекста.__enter__()
загружается для последующего использования в контекстном менеджере.__exit__()
загружается для последующего использования в контекстном менеджере.Вызывается метод контекстного менеджера
__enter__()
.Если целевой объект был включен в инструкцию
with
, ему присваивается возвращаемое значение из__enter__()
.Примечание
Оператор
with
гарантирует, что если метод__enter__()
возвращает результат без ошибки, то всегда будет вызываться метод__exit__()
. Таким образом, если во время присвоения целевому списку произойдет ошибка, она будет обработана так же, как и ошибка, возникшая в наборе. Смотрите шаг 7 ниже.Набор выполнен.
Вызывается метод контекстного менеджера
__exit__()
. Если исключение привело к выходу из пакета, его тип, значение и обратная трассировка передаются в качестве аргументов в__exit__()
. В противном случае вводятся три аргументаNone
.Если из набора данных был выполнен выход из-за исключения, а возвращаемое значение из метода
__exit__()
было ложным, исключение создается повторно. Если возвращаемое значение равно true, исключение подавляется, и выполнение продолжается с инструкцией, следующей за инструкциейwith
.Если выход из пакета был выполнен по какой-либо причине, отличной от исключения, возвращаемое значение из
__exit__()
игнорируется, и выполнение продолжается в обычном месте для того типа выхода, который был выбран.
Следующий код:
with EXPRESSION as TARGET:
SUITE
семантически эквивалентно:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
При наличии более чем одного элемента контекстные менеджеры обрабатываются так, как если бы было вложено несколько инструкций with
:
with A() as a, B() as b:
SUITE
семантически эквивалентно:
with A() as a:
with B() as b:
SUITE
Вы также можете написать контекстные менеджеры с несколькими элементами в нескольких строках, если элементы заключены в круглые скобки. Например:
with (
A() as a,
B() as b,
):
SUITE
Изменено в версии 3.1: Поддержка нескольких контекстных выражений.
Изменено в версии 3.10: Поддерживается использование группирующих круглых скобок для разбивки инструкции на несколько строк.
8.6. Оператор match
¶
Добавлено в версии 3.10.
Оператор match используется для сопоставления с образцом. Синтаксис:
match_stmt ::= 'match'subject_expr
":" NEWLINE INDENTcase_block
+ DEDENT subject_expr ::=star_named_expression
","star_named_expressions
? |named_expression
case_block ::= 'case'patterns
[guard
] ":"block
Примечание
В этом разделе используются одинарные кавычки для обозначения soft keywords.
При сопоставлении с шаблоном в качестве входных данных используется шаблон (следующий за case
) и предметное значение (следующее за match
). Шаблон (который может содержать подшаблоны) сопоставляется с предметным значением. Результаты следующие:
Успешное или неудачное совпадение (также называемое успехом или неудачей шаблона).
Возможна привязка совпадающих значений к имени. Предварительные условия для этого дополнительно обсуждаются ниже.
Ключевыми словами match
и case
являются soft keywords.
См.также
8.6.1. Обзор¶
Вот краткий обзор логического хода выполнения инструкции match:
Вычисляется подчиненное выражение
subject_expr
и в результате получается подчиненное значение. Если подчиненное выражение содержит запятую, кортеж создается с использованием the standard rules.Для каждого шаблона в
case_block
выполняется попытка сопоставления со значением объекта. Ниже описаны конкретные правила для успешного или неуспешного выполнения. Попытка сопоставления также может связывать некоторые или все отдельные имена в шаблоне. Точные правила привязки к шаблону зависят от типа шаблона и указаны ниже. Привязки имен, сделанные во время успешного сопоставления с шаблоном, переживают выполненный блок и могут быть использованы после инструкции match.Примечание
Во время неудачных совпадений с шаблонами некоторые вложенные шаблоны могут быть успешными. Не полагайтесь на то, что для неудачного совпадения были созданы привязки. И наоборот, не полагайтесь на то, что переменные остаются неизменными после неудачного совпадения. Точное поведение зависит от реализации и может варьироваться. Это преднамеренное решение, принятое для того, чтобы позволить различным реализациям добавлять оптимизацию.
Если шаблон выполняется успешно, вычисляется соответствующая защита (если она присутствует). В этом случае гарантируется, что все привязки имен выполнены.
Если защита оценивается как true или отсутствует, выполняется
block
внутриcase_block
.В противном случае выполняется следующая попытка
case_block
, как описано выше.Если больше нет блоков case, оператор match завершается.
Примечание
Как правило, пользователям не следует полагаться на вычисляемый шаблон. В зависимости от реализации интерпретатор может кэшировать значения или использовать другие оптимизации, которые позволяют избежать повторных вычислений.
Пример заявления о совпадении:
>>> flag = False
>>> match (100, 200):
... case (100, 300): # Mismatch: 200 != 300
... print('Case 1')
... case (100, 200) if flag: # Successful match, but guard fails
... print('Case 2')
... case (100, y): # Matches and binds y to 200
... print(f'Case 3, y: {y}')
... case _: # Pattern not attempted
... print('Case 4, I match anything!')
...
Case 3, y: 200
В данном случае if flag
- это защита. Подробнее об этом читайте в следующем разделе.
8.6.2. Стража¶
guard ::= "if" named_expression
Для выполнения кода внутри блока case
должен быть выполнен guard
(который является частью case
). Он принимает вид: if
, за которым следует выражение.
Логический поток case
блока с guard
следует следующим образом:
Убедитесь, что шаблон в блоке
case
выполнен успешно. Если шаблон не выполнен,guard
не вычисляется и проверяется следующий блокcase
.Если шаблон сработал успешно, оцените значение
guard
.Если условие
guard
оценивается как истинное, выбирается блок case.Если условие
guard
оценивается как ложное, блок регистра не выбирается.Если
guard
вызывает исключение во время вычисления, оно всплывает в виде пузырька.
Защитным элементам разрешено иметь побочные эффекты, поскольку они являются выражениями. Оценка защитных элементов должна выполняться от первого до последнего блока case, по одному за раз, пропуская блоки case, шаблоны которых не все выполняются успешно. (т.е. оценка защитных элементов должна выполняться по порядку). Оценка защиты должна быть прекращена, как только будет выбран блок обращения.
8.6.3. Неопровержимые прецедентные блоки¶
Блок неопровержимых обращений - это блок совпадений для всех обращений. Оператор соответствия может содержать не более одного блока неопровержимых обращений, и он должен быть последним.
Блок case считается неопровержимым, если у него нет защиты и его шаблон является неопровержимым. Шаблон считается неопровержимым, если мы можем доказать на основе одного только его синтаксиса, что он всегда будет успешным. Неопровержимыми являются только следующие шаблоны:
КАК закономерности чья левая сторона неопровержима
ИЛИ Узоры содержит по крайней мере одну неопровержимую закономерность
неопровержимые закономерности, заключенные в круглые скобки
8.6.4. Узоры¶
Примечание
В этом разделе используются грамматические обозначения, выходящие за рамки стандартного EBNF:
обозначение
SEP.RULE+
является сокращением отRULE (SEP RULE)*
обозначение
!RULE
является сокращением для отрицательного предварительного утверждения
Синтаксис верхнего уровня для patterns
следующий:
patterns ::=open_sequence_pattern
|pattern
pattern ::=as_pattern
|or_pattern
closed_pattern ::= |literal_pattern
|capture_pattern
|wildcard_pattern
|value_pattern
|group_pattern
|sequence_pattern
|mapping_pattern
|class_pattern
Приведенные ниже описания будут включать в себя описание «простыми словами» того, что делает шаблон для иллюстрации (авторство принадлежит Рэймонду Хеттингеру (Raymond Hettinger) за документ, который послужил основой для большинства описаний). Обратите внимание, что эти описания даны исключительно для иллюстрации и могут не отражать основную реализацию. Кроме того, они охватывают не все действительные формы.
8.6.4.1. ИЛИ Узоры¶
Шаблон OR - это два или более шаблона, разделенных вертикальными полосами |
. Синтаксис:
or_pattern ::= "|".closed_pattern
+
Только последний подшаблон может быть irrefutable, и каждый подшаблон должен содержать один и тот же набор имен, чтобы избежать двусмысленности.
Шаблон OR по очереди сопоставляет каждый из своих подшаблонов с заданным значением, пока один из них не завершится успешно. Затем шаблон OR считается успешным. В противном случае, если ни один из подшаблонов не завершится успешно, шаблон OR завершится ошибкой.
Проще говоря, P1 | P2 | ...
попытается найти соответствие P1
, если это не удастся, он попытается найти соответствие P2
, немедленно завершая работу, если что-то удастся, и терпя неудачу в противном случае.
8.6.4.2. КАК закономерности¶
Шаблон AS соответствует шаблону OR, расположенному слева от ключевого слова as
напротив темы. Синтаксис:
as_pattern ::=or_pattern
"as"capture_pattern
Если шаблон OR не работает, то и шаблон AS не работает. В противном случае шаблон AS привязывает объект к имени справа от ключевого слова as и завершается успешно. capture_pattern
не может быть _
.
Проще говоря, P as NAME
будет соответствовать P
, а в случае успеха будет установлено NAME = <subject>
.
8.6.4.3. Буквальные паттерны¶
Буквальный шаблон соответствует большинству literals в Python. Синтаксис:
literal_pattern ::=signed_number
|signed_number
"+" NUMBER |signed_number
"-" NUMBER |strings
| "None" | "True" | "False" |signed_number
: NUMBER | "-" NUMBER
Правило strings
и токен NUMBER
определены в standard Python grammar. Поддерживаются строки, заключенные в тройные кавычки. Поддерживаются необработанные строки и байтовые строки. f-струны не поддерживаются.
Формы signed_number '+' NUMBER
и signed_number '-' NUMBER
предназначены для выражения complex numbers; для них требуется действительное число слева и мнимое число справа. Например, 3 + 4j
.
Проще говоря, LITERAL
будет успешным только в том случае, если <subject> == LITERAL
. Для синглтонов None
, True
и False
используется оператор is
.
8.6.4.4. Захватывать шаблоны¶
Шаблон захвата привязывает значение объекта к имени. Синтаксис:
capture_pattern ::= !'_' NAME
Одиночное подчеркивание _
не является шаблоном записи (это то, что выражает !'_'
). Вместо этого оно рассматривается как wildcard_pattern
.
В данном шаблоне данное имя может быть привязано только один раз. Например, case x, x: ...
недопустимо, в то время как case [x] | x: ...
разрешено.
Шаблоны перехвата всегда выполняются успешно. Привязка выполняется в соответствии с правилами определения области видимости, установленными оператором выражения присваивания в PEP 572; имя становится локальной переменной в ближайшей области, содержащей функцию, если только не существует применимого оператора global
или nonlocal
.
Проще говоря, NAME
всегда будет успешным, и он установит NAME = <subject>
.
8.6.4.5. Шаблоны с подстановочными знаками¶
Шаблон подстановки всегда выполняется успешно (соответствует чему угодно) и не привязывает никакое имя. Синтаксис:
wildcard_pattern ::= '_'
_
- это soft keyword внутри любого шаблона, но только внутри шаблонов. Как обычно, это идентификатор, даже внутри match
выражений subject, guard
s и case
блоков.
Проще говоря, _
всегда будет успешным.
8.6.4.6. Ценностные паттерны¶
Шаблон value представляет собой именованное значение в Python. Синтаксис:
value_pattern ::=attr
attr ::=name_or_attr
"." NAME name_or_attr ::=attr
| NAME
Пунктирное имя в шаблоне ищется с помощью стандартного кода Python name resolution rules. Поиск шаблона завершается успешно, если найденное значение совпадает со значением объекта (с использованием оператора равенства ==
).
Проще говоря, NAME1.NAME2
будет успешным только в том случае, если <subject> == NAME1.NAME2
Примечание
Если одно и то же значение встречается несколько раз в одном и том же операторе match, интерпретатор может кэшировать первое найденное значение и повторно использовать его, а не повторять один и тот же поиск. Этот кэш строго привязан к конкретному выполнению данного оператора match.
8.6.4.7. Групповые паттерны¶
Групповой шаблон позволяет пользователям заключать шаблоны в круглые скобки, чтобы подчеркнуть предполагаемую группировку. В противном случае он не имеет дополнительного синтаксиса. Синтаксис:
group_pattern ::= "(" pattern
")"
Проще говоря, (P)
имеет тот же эффект, что и P
.
8.6.4.8. Шаблоны последовательностей¶
Шаблон последовательности содержит несколько вложенных шаблонов, которые должны быть сопоставлены с элементами последовательности. Синтаксис аналогичен распаковке списка или кортежа.
sequence_pattern ::= "[" [maybe_sequence_pattern
] "]" | "(" [open_sequence_pattern
] ")" open_sequence_pattern ::=maybe_star_pattern
"," [maybe_sequence_pattern
] maybe_sequence_pattern ::= ",".maybe_star_pattern
+ ","? maybe_star_pattern ::=star_pattern
|pattern
star_pattern ::= "*" (capture_pattern
|wildcard_pattern
)
Нет никакой разницы, используются ли круглые или квадратные скобки для шаблонов последовательности (т.е. (...)
против [...]
).
Примечание
Единственный шаблон, заключенный в круглые скобки без запятой в конце (например, (3 | 4)
), обозначается как group pattern. В то время как отдельный шаблон, заключенный в квадратные скобки (например, [3 | 4]
), по-прежнему является шаблоном последовательности.
В шаблоне последовательности может быть не более одного элемента в виде звезды. Элемент в виде звезды может находиться в любом положении. Если элемент в виде звезды отсутствует, то шаблон последовательности является шаблоном последовательности фиксированной длины; в противном случае это шаблон последовательности переменной длины.
Ниже приведен логический порядок сопоставления шаблона последовательности со значением объекта:
Если значение subject не является последовательностью [2], то шаблон последовательности не выполняется.
Если значение subject является экземпляром
str
,bytes
илиbytearray
, то шаблон последовательности не выполняется.Последующие шаги зависят от того, является ли шаблон последовательности фиксированной или переменной длины.
Если шаблон последовательности имеет фиксированную длину:
Если длина предметной последовательности не равна количеству подшаблонов, то шаблон последовательности не выполняется
Подшаблоны в шаблоне последовательности сопоставляются с соответствующими элементами в последовательности объектов слева направо. Сопоставление прекращается, как только какой-либо подшаблон завершается ошибкой. Если все подшаблоны успешно соответствуют соответствующему элементу, шаблон последовательности завершается успешно.
В противном случае, если шаблон последовательности имеет переменную длину:
Если длина последовательности объектов меньше, чем количество не звездообразных подшаблонов, то шаблон последовательности не выполняется.
Ведущие подшаблоны, не являющиеся звездами, сопоставляются с соответствующими им элементами, как и для последовательностей фиксированной длины.
Если предыдущий шаг выполнен успешно, подшаблон «звездочка» соответствует списку, сформированному из оставшихся тематических элементов, за исключением оставшихся элементов, соответствующих подшаблонам без звездочек, следующим за подшаблоном «звездочка».
Остальные подшаблоны, не являющиеся звездочками, сопоставляются с соответствующими им тематическими элементами, как для последовательности фиксированной длины.
Примечание
Длина последовательности объектов определяется с помощью
len()
(т.е. с помощью протокола__len__()
). Эта длина может кэшироваться интерпретатором аналогично value patterns.
Проще говоря, [P1, P2, P3,
… , P<N>]
совпадает только в том случае, если выполняется все следующее:
проверка
<subject>
- это последовательностьlen(subject) == <N>
P1
совпадает с<subject>[0]
(обратите внимание, что это совпадение также может связывать имена)P2
совпадает с<subject>[1]
(обратите внимание, что это совпадение также может связывать имена)… и так далее для соответствующего шаблона/элемента.
8.6.4.9. Отображение шаблонов¶
Шаблон сопоставления содержит один или несколько шаблонов «ключ-значение». Синтаксис аналогичен построению словаря. Синтаксис:
mapping_pattern ::= "{" [items_pattern
] "}" items_pattern ::= ",".key_value_pattern
+ ","? key_value_pattern ::= (literal_pattern
|value_pattern
) ":"pattern
|double_star_pattern
double_star_pattern ::= "**"capture_pattern
В шаблоне отображения может быть не более одной двойной звездочки. Шаблон двойной звезды должен быть последним подшаблоном в шаблоне отображения.
Дублирующиеся ключи в шаблонах сопоставления запрещены. Дублирующиеся литеральные ключи вызовут значение SyntaxError
. Два ключа, которые в противном случае имели бы одинаковое значение, вызовут значение ValueError
во время выполнения.
Ниже приведен логический порядок сопоставления шаблона сопоставления со значением объекта:
Если значение subject не является отображением [3], шаблон отображения не выполняется.
Если каждый ключ, указанный в шаблоне сопоставления, присутствует в тематическом сопоставлении, и шаблон для каждого ключа соответствует соответствующему элементу тематического сопоставления, шаблон сопоставления выполняется успешно.
Если в шаблоне сопоставления обнаружены повторяющиеся ключи, шаблон считается недействительным. Для повторяющихся буквенных значений задается значение
SyntaxError
илиValueError
для именованных ключей с одинаковым значением.
Примечание
Пары ключ-значение сопоставляются с использованием формы с двумя аргументами метода get()
объекта сопоставления. Совпадающие пары ключ-значение уже должны присутствовать в сопоставлении, а не создаваться «на лету» с помощью __missing__()
или __getitem__()
.
Проще говоря, {KEY1: P1, KEY2: P2, ... }
совпадает только в том случае, если происходит все следующее:
проверка
<subject>
является отображениемKEY1 in <subject>
P1
совпадений<subject>[KEY1]
… и так далее для соответствующей пары КЛЮЧ/шаблон.
8.6.4.10. Шаблоны классов¶
Шаблон class представляет класс и его позиционные аргументы и аргументы ключевых слов (если таковые имеются). Синтаксис:
class_pattern ::=name_or_attr
"(" [pattern_arguments
","?] ")" pattern_arguments ::=positional_patterns
[","keyword_patterns
] |keyword_patterns
positional_patterns ::= ",".pattern
+ keyword_patterns ::= ",".keyword_pattern
+ keyword_pattern ::= NAME "="pattern
Одно и то же ключевое слово не должно повторяться в шаблонах классов.
Ниже приведен логический порядок сопоставления шаблона класса со значением объекта:
Если
name_or_attr
не является экземпляром встроенногоtype
, вызовитеTypeError
.Если значение subject не является экземпляром
name_or_attr
(проверено с помощьюisinstance()
), шаблон class не выполняется.Если аргументы шаблона отсутствуют, то шаблон выполняется успешно. В противном случае последующие шаги зависят от того, присутствуют ли шаблоны ключевых слов или позиционных аргументов.
Для ряда встроенных типов (указанных ниже) используется один позиционный подшаблон, который будет соответствовать всей теме; для этих типов шаблоны ключевых слов также работают, как и для других типов.
Если присутствуют только шаблоны ключевых слов, они обрабатываются следующим образом, один за другим:
I. Ключевое слово ищется как атрибут по теме.
Если при этом возникает исключение, отличное от
AttributeError
, оно всплывает.Если при этом возникает
AttributeError
, то в шаблоне класса произошел сбой.В противном случае подшаблон, связанный с шаблоном ключевого слова, сопоставляется со значением атрибута subject. Если это не удается, то происходит сбой шаблона class; если это удается, то выполняется переход к следующему ключевому слову.
ii. Если все шаблоны ключевых слов выполнены успешно, то и шаблон класса будет выполнен успешно.
Если присутствуют какие-либо позиционные шаблоны, они преобразуются в шаблоны ключевых слов с использованием атрибута
__match_args__
в классеname_or_attr
перед сопоставлением:I. Вызывается эквивалент
getattr(cls, "__match_args__", ())
.Если при этом возникает исключение, оно всплывает в виде пузырька.
Если возвращаемое значение не является кортежем, преобразование завершается ошибкой и генерируется значение
TypeError
.Если позиционных паттернов больше, чем
len(cls.__match_args__)
,TypeError
, то повышается значение.В противном случае позиционный шаблон
i
преобразуется в шаблон ключевого слова с использованием__match_args__[i]
в качестве ключевого слова.__match_args__[i]
должен быть строкой; если нет, то выводитсяTypeError
.Если есть повторяющиеся ключевые слова, выводится значение
TypeError
.
- ii. Как только все позиционные шаблоны будут преобразованы в шаблоны ключевых слов,
сопоставление происходит так, как если бы существовали только шаблоны ключевых слов.
Для следующих встроенных типов обработка позиционных вложенных шаблонов отличается:
Эти классы принимают один позиционный аргумент, и шаблон в них сопоставляется со всем объектом, а не с атрибутом. Например,
int(0|1)
соответствует значению0
, но не значению0.0
.
Проще говоря, CLS(P1, attr=P2)
совпадает только в том случае, если происходит следующее:
isinstance(<subject>, CLS)
преобразуйте
P1
в шаблон ключевого слова, используяCLS.__match_args__
Для каждого ключевого слова аргумент
attr=P2
:hasattr(<subject>, "attr")
P2
совпадений<subject>.attr
… и так далее для соответствующей пары аргумент ключевого слова/шаблон.
8.7. Определения функций¶
Определение функции определяет пользовательский функциональный объект (см. раздел Иерархия стандартных типов).:
funcdef ::= [decorators
] "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
decorators ::=decorator
+ decorator ::= "@"assignment_expression
NEWLINE parameter_list ::=defparameter
(","defparameter
)* "," "/" ["," [parameter_list_no_posonly
]] |parameter_list_no_posonly
parameter_list_no_posonly ::=defparameter
(","defparameter
)* ["," [parameter_list_starargs
]] |parameter_list_starargs
parameter_list_starargs ::= "*" [parameter
] (","defparameter
)* ["," ["**"parameter
[","]]] | "**"parameter
[","] parameter ::=identifier
[":"expression
] defparameter ::=parameter
["="expression
] funcname ::=identifier
Определение функции - это исполняемая инструкция. При ее выполнении имя функции в текущем локальном пространстве имен привязывается к объекту function (оболочке исполняемого кода функции). Этот объект function содержит ссылку на текущее глобальное пространство имен в качестве глобального пространства имен, которое будет использоваться при вызове функции.
Определение функции не выполняет тело функции; оно выполняется только при вызове функции. [4]
Определение функции может быть обернуто одним или несколькими выражениями decorator. Выражения декоратора вычисляются, когда функция определена, в области, содержащей определение функции. Результатом должен быть вызываемый объект, который вызывается с использованием объекта функции в качестве единственного аргумента. Возвращаемое значение привязывается к имени функции, а не к объекту функции. Несколько декораторов применяются вложенным образом. Например, следующий код
@f1(arg)
@f2
def func(): pass
примерно эквивалентно
def func(): pass
func = f1(arg)(f2(func))
за исключением того, что исходная функция временно не привязана к имени func
.
Изменено в версии 3.9: Функции могут быть оформлены любым допустимым значением assignment_expression
. Ранее грамматика была гораздо более строгой; подробности смотрите в PEP 614.
Когда один или несколько parameters имеют вид параметр =
выражение, считается, что функция имеет «значения параметров по умолчанию». Для параметра со значением по умолчанию соответствующее argument может быть опущено при вызове, и в этом случае заменяется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры вплоть до «*
» также должны иметь значение по умолчанию - это синтаксическое ограничение, которое не выражается грамматикой.
Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции. Это означает, что выражение вычисляется один раз, когда функция определена, и что для каждого вызова используется одно и то же «предварительно вычисленное» значение. Это особенно важно понимать, когда значение параметра по умолчанию является изменяемым объектом, таким как список или словарь: если функция изменяет объект (например, путем добавления элемента в список), значение параметра по умолчанию фактически изменяется. Как правило, это не то, что было задумано. Способ обойти это - использовать None
в качестве значения по умолчанию и явно протестировать его в теле функции, например:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
Семантика вызова функции более подробно описана в разделе Звонки. Вызов функции всегда присваивает значения всем параметрам, указанным в списке параметров, либо из позиционных аргументов, либо из аргументов ключевых слов, либо из значений по умолчанию. Если присутствует форма «*identifier
», она инициализируется кортежем, получающим любые избыточные позиционные параметры, по умолчанию используется пустой кортеж. Если присутствует форма «**identifier
», она инициализируется новым упорядоченным отображением, получающим все лишние аргументы ключевого слова, по умолчанию используется новое пустое отображение того же типа. Параметры после «*
» или «*identifier
» являются параметрами только для ключевых слов и могут передаваться только с помощью аргументов ключевых слов. Параметры перед «/
» являются позиционными параметрами и могут передаваться только с помощью позиционных аргументов.
Изменено в версии 3.8: Синтаксис функционального параметра /
может использоваться для указания только позиционных параметров. Подробности см. в PEP 570.
Параметры могут иметь значение annotation в виде «: expression
», следующее за именем параметра. Любой параметр может иметь аннотацию, даже в виде *identifier
или **identifier
. Функции могут иметь аннотацию «return» вида «-> expression
» после списка параметров. Эти аннотации могут быть любым допустимым выражением Python. Наличие аннотаций не изменяет семантику функции. Значения аннотаций доступны в виде значений справочника, определяемого именами параметров в атрибуте __annotations__
объекта function. Если используется импорт annotations
из __future__
, аннотации сохраняются в виде строк во время выполнения, что позволяет выполнять отложенную оценку. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут быть вычислены в порядке, отличном от того, в котором они отображаются в исходном коде.
Также возможно создавать анонимные функции (функции, не привязанные к имени) для немедленного использования в выражениях. При этом используются лямбда-выражения, описанные в разделе Лямбды. Обратите внимание, что лямбда-выражение является всего лишь сокращением для упрощенного определения функции; функция, определенная в инструкции «def
», может быть передана другим способом или присвоена другому имени точно так же, как функция, определенная с помощью лямбда-выражения. Форма «def
» на самом деле более мощная, поскольку она позволяет выполнять несколько инструкций и аннотаций.
Примечание программиста: Функции - это первоклассные объекты. Оператор «def
», выполняемый внутри определения функции, определяет локальную функцию, которая может быть возвращена или передана другим пользователям. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробности см. в разделе Присвоение имен и привязка.
См.также
- PEP 3107 - Функциональные аннотации
Исходная спецификация для функциональных аннотаций.
- PEP 484 - Введите подсказки
Определение стандартного значения для аннотаций: введите подсказки.
- PEP 526 - Синтаксис для аннотаций переменных
Возможность вводить объявления переменных с подсказками, включая переменные класса и переменные экземпляра.
- PEP 563 - Отложенная оценка аннотаций
Поддержка прямых ссылок в аннотациях за счет сохранения аннотаций во время выполнения в строковом формате вместо предварительной оценки.
- PEP 318 - Декораторы для функций и методов
Были введены декораторы функций и методов. Декораторы классов были введены в PEP 3129.
8.8. Определения классов¶
Определение класса определяет объект класса (см. раздел Иерархия стандартных типов).:
classdef ::= [decorators
] "class"classname
[inheritance
] ":"suite
inheritance ::= "(" [argument_list
] ")" classname ::=identifier
Определение класса - это исполняемая инструкция. Список наследования обычно содержит список базовых классов (см. Метаклассы для более подробного использования), поэтому каждый элемент в списке должен быть преобразован в объект класса, который допускает создание подклассов. Классы без списка наследования наследуются, по умолчанию, от базового класса object
; следовательно,
class Foo:
pass
эквивалентно
class Foo(object):
pass
Затем набор класса выполняется в новом фрейме выполнения (см. Присвоение имен и привязка), используя вновь созданное локальное пространство имен и исходное глобальное пространство имен. (Обычно набор содержит в основном определения функций). Когда набор классов завершает выполнение, его фрейм выполнения удаляется, но сохраняется его локальное пространство имен. [5] Затем создается объект класса, используя список наследования для базовых классов и сохраненное локальное пространство имен для словаря атрибутов. Имя класса привязано к этому объекту класса в исходном локальном пространстве имен.
Порядок, в котором атрибуты определены в теле класса, сохраняется в __dict__
нового класса. Обратите внимание, что это является надежным только сразу после создания класса и только для классов, которые были определены с использованием синтаксиса определения.
Создание класса может быть сильно изменено с помощью metaclasses.
Классы также могут быть украшены: точно так же, как при оформлении функций,
@f1(arg)
@f2
class Foo: pass
примерно эквивалентно
class Foo: pass
Foo = f1(arg)(f2(Foo))
Правила вычисления для выражений декоратора такие же, как и для декораторов функций. Затем результат привязывается к имени класса.
Изменено в версии 3.9: Классы могут быть оформлены любым допустимым значением assignment_expression
. Ранее грамматика была гораздо более строгой; подробности смотрите в PEP 614.
Примечание программиста: Переменные, определенные в определении класса, являются атрибутами класса; они являются общими для экземпляров. Атрибуты экземпляра могут быть заданы в методе с помощью self.name = value
. Как атрибуты класса, так и экземпляра доступны через обозначение «self.name
», и атрибут экземпляра скрывает атрибут класса с таким же именем, когда к нему обращаются таким образом. Атрибуты класса могут использоваться в качестве значений по умолчанию для атрибутов экземпляра, но использование изменяемых значений может привести к неожиданным результатам. Descriptors может использоваться для создания переменных экземпляра с различными деталями реализации.
См.также
- PEP 3115 - Метаклассы в Python 3000
Предложение, которое изменило объявление метаклассов на текущий синтаксис и семантику того, как создаются классы с метаклассами.
- PEP 3129 - Декораторы классов
Предложение, в котором добавлены декораторы классов. Декораторы функций и методов были представлены в PEP 318.
8.9. Сопрограммы¶
Добавлено в версии 3.5.
8.9.1. Определение функции сопрограммы¶
async_funcdef ::= [decorators
] "async" "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
Выполнение сопрограмм Python может быть приостановлено и возобновлено во многих точках (см. coroutine). await
выражения async for
и async with
могут использоваться только в теле функции сопрограммы.
Функции, определенные с помощью синтаксиса async def
, всегда являются функциями сопрограммы, даже если они не содержат ключевых слов await
или async
.
Это SyntaxError
для использования выражения yield from
внутри тела функции сопрограммы.
Пример функции сопрограммы:
async def func(param1, param2):
do_stuff()
await some_coroutine()
Изменено в версии 3.7: await
и async
теперь являются ключевыми словами; ранее они рассматривались как таковые только внутри тела сопрограммы.
8.9.2. Оператор async for
¶
async_for_stmt ::= "async" for_stmt
asynchronous iterable предоставляет метод __aiter__
, который напрямую возвращает asynchronous iterator, который может вызывать асинхронный код в своем методе __anext__
.
Оператор async for
обеспечивает удобную итерацию по асинхронным итерационным параметрам.
Следующий код:
async for TARGET in ITER:
SUITE
else:
SUITE2
Семантически эквивалентно:
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True
while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
Смотрите также __aiter__()
и __anext__()
для получения дополнительной информации.
Это SyntaxError
для использования инструкции async for
вне тела функции сопрограммы.
8.9.3. Оператор async with
¶
async_with_stmt ::= "async" with_stmt
asynchronous context manager - это context manager, который может приостановить выполнение с помощью своих методов enter и exit.
Следующий код:
async with EXPRESSION as TARGET:
SUITE
семантически эквивалентно:
manager = (EXPRESSION)
aenter = type(manager).__aenter__
aexit = type(manager).__aexit__
value = await aenter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(manager, None, None, None)
Смотрите также __aenter__()
и __aexit__()
для получения дополнительной информации.
Это SyntaxError
для использования инструкции async with
вне тела функции сопрограммы.
См.также
- PEP 492 - Сопрограммы с асинхронным синтаксисом и ожиданием
Предложение, которое сделало сопрограммы полноценной самостоятельной концепцией в Python и добавило вспомогательный синтаксис.
Сноски