Составные инструкции
Составные инструкции содержат другие инструкции (или их группы); они тем или иным образом влияют на выполнение этих инструкций или управляют им. Как правило, составные инструкции занимают несколько строк, хотя в простых случаях вся составная инструкция может уместиться в одной строке.
Инструкции 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 INDENT statement+ 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]
Она выбирает ровно один блок, последовательно вычисляя выражения, пока одно из них не окажется истинным (определения истинности и ложности см. в разделе Логические операции); затем выполняется этот блок (а остальные части инструкции 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_expression_list ":" suite ["else" ":" suite]
Выражение starred_expression_list вычисляется один раз; в результате должен получиться итерируемый объект. Для этого объекта создаётся итератор. Первый элемент, предоставленный итератором, присваивается целевому списку по стандартным правилам присваивания (см. раздел Инструкции присваивания), после чего выполняется блок. Это повторяется для каждого элемента, предоставленного итератором. Когда элементы итератора заканчиваются, выполняется блок части 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.
Изменено в версии 3.14: Добавлена поддержка опционального опускания группирующих скобок при указании нескольких типов исключений. См. PEP 758.
8.4.1. Часть except
Часть(и) except задают один или несколько обработчиков исключений. Если в части try исключение не возникает, обработчики исключений не выполняются. Если исключение возникает в блоке try, начинается поиск обработчика исключений. В ходе поиска части except проверяются по очереди, пока не найдётся та, которая соответствует исключению. Часть except без выражения, если она присутствует, должна быть последней; она соответствует любому исключению.
В части except с выражением это выражение должно вычисляться в тип исключения или кортеж типов исключений. Если указано несколько типов исключений и часть as не используется, скобки можно опустить. Возбуждённое исключение соответствует части except, если её выражение вычисляется в класс исключения или в невиртуальный базовый класс объекта исключения либо в кортеж, содержащий такой класс.
Если ни одна часть 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* задают один или несколько обработчиков групп исключений (экземпляров BaseExceptionGroup). Инструкция try может содержать части except или except*, но не обе одновременно. В случае except* тип исключения для сопоставления указывать обязательно, поэтому except*: является синтаксической ошибкой. Тип интерпретируется так же, как в случае except, но сопоставление выполняется с исключениями, содержащимися в обрабатываемой группе. Если сопоставляемый тип является подклассом BaseExceptionGroup, вызывается исключение TypeError, поскольку в этом случае семантика была бы неоднозначной.
Когда в блоке try возникает группа исключений, каждая часть except* разделяет её (см. split()) на подгруппы соответствующих и несоответствующих исключений. Если подгруппа соответствующих исключений не пуста, она становится обрабатываемым исключением (значением, возвращаемым sys.exception()) и присваивается цели части except*, если она указана. Затем выполняется тело части except*. Если подгруппа несоответствующих исключений не пуста, она обрабатывается следующей частью except* таким же образом. Это продолжается, пока не будут сопоставлены все исключения в группе или не выполнится последняя часть 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 "<doctest default[0]>", line 2, in <module>
| raise ExceptionGroup("eg",
| [ValueError(1), TypeError(2), OSError(3), OSError(4)])
| ExceptionGroup: eg (1 sub-exception)
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
Если исключение, возникшее в блоке try, не является группой исключений и его тип соответствует одной из частей except*, оно перехватывается и оборачивается в группу исключений с пустой строкой в качестве сообщения. Это гарантирует, что тип цели e всегда будет BaseExceptionGroup:
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError(),))
Инструкции 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, сохранённое исключение отбрасывается. Например, эта функция возвращает 42.
def f():
try:
1/0
finally:
return 42
Во время выполнения части finally сведения об исключении программе недоступны.
Когда в блоке try инструкции try…finally выполняется инструкция return, break или continue, часть finally также выполняется «при выходе».
Возвращаемое функцией значение определяется последней выполненной инструкцией return. Поскольку часть finally выполняется всегда, инструкция return в части finally всегда будет последней выполненной. Следующая функция возвращает значение «finally».
def foo():
try:
return 'try'
finally:
return 'finally'
Изменено в версии 3.8: До Python 3.8 инструкция continue была недопустима в части finally из-за ошибки реализации.
Изменено в версии 3.14: Компилятор выдаёт предупреждение SyntaxWarning, если в блоке finally встречается инструкция return, break или continue (см. PEP 765).
8.5. Инструкция with
Инструкция 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 с одним «элементом» происходит следующим образом:
- Вычисляется выражение контекста (выражение, указанное в
with_item), чтобы получить менеджер контекста. - Для последующего использования загружается метод
__enter__()менеджера контекста. - Для последующего использования загружается метод
__exit__()менеджера контекста. - Вызывается метод
__enter__()менеджера контекста. -
Если в инструкции
withуказана цель, ей присваивается возвращаемое значение__enter__().Примечание
Инструкция
withгарантирует, что если метод__enter__()завершится без ошибки, то__exit__()будет вызван всегда. Поэтому ошибка при присваивании целевому списку будет обработана так же, как ошибка, возникшая внутри блока. См. шаг 7 ниже. - Выполняется блок.
-
Вызывается метод
__exit__()менеджера контекста. Если выход из блока был вызван исключением, его тип, значение и трассировка передаются в качестве аргументов методу__exit__(). В противном случае передаются три аргументаNone.Если выход из блока был вызван исключением и возвращаемое значение метода
__exit__()было ложным, исключение возбуждается повторно. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается с инструкции, следующей за инструкциейwith.Если выход из блока произошёл по любой причине, кроме исключения, возвращаемое значение метода
__exit__()игнорируется, и выполнение продолжается в обычном месте для соответствующего типа выхода.
Следующий код:
with EXPRESSION as TARGET:
SUITE
семантически эквивалентен:
manager = (EXPRESSION)
enter = manager.__enter__
exit = manager.__exit__
value = enter()
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(*sys.exc_info()):
raise
finally:
if not hit_except:
exit(None, None, None)
за исключением того, что для __enter__() и __exit__() используется неявный поиск специальных методов.
Если указано несколько элементов, менеджеры контекста обрабатываются так, как если бы несколько инструкций 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 INDENT case_block+ DEDENT subject_expr: flexible_expression "," [flexible_expression_list [',']] | assignment_expression case_block: 'case' patterns [guard] ":" suite
Примечание
В этом разделе для обозначения мягких ключевых слов используются одинарные кавычки.
Сопоставление с образцом принимает на вход образец (следующий за case) и значение субъекта (следующее за match). Образец (который может содержать подобразцы) сопоставляется со значением субъекта. Возможны следующие результаты:
- Успешное или неуспешное сопоставление (также называемое успешным или неуспешным совпадением с образцом).
- Возможная привязка сопоставленных значений к имени. Условия для этого подробнее обсуждаются ниже.
Ключевые слова match и case являются мягкими ключевыми словами.
См. также
8.6.1. Обзор
Ниже представлен обзор логического потока выполнения инструкции match:
- Вычисляется выражение субъекта
subject_exprи получается результирующее значение субъекта. Если выражение субъекта содержит запятую, кортеж создаётся в соответствии с стандартными правилами. -
Каждый образец в
case_blockпо очереди пытаются сопоставить со значением субъекта. Конкретные правила успешного или неуспешного сопоставления описаны ниже. При попытке сопоставления также может быть выполнена привязка некоторых или всех отдельных имён в образце. Точные правила привязки образцов различаются в зависимости от типа образца и приведены ниже. Имена, привязанные при успешном сопоставлении с образцом, остаются доступны после выполнения блока и могут использоваться после инструкции match.Примечание
При неудачном сопоставлении с образцом некоторые подобразцы могут успешно сопоставиться. Не полагайтесь на то, что при неудачном сопоставлении будут выполнены привязки. И наоборот, не полагайтесь на то, что после неудачного сопоставления переменные останутся неизменными. Точное поведение зависит от реализации и может различаться. Такое решение принято намеренно, чтобы разные реализации могли добавлять оптимизации.
-
Если образец успешно сопоставился, вычисляется соответствующее условие (если оно есть). В этом случае гарантируется, что все привязки имён уже выполнены.
- Если условие вычисляется как истинное или отсутствует, выполняется
blockвнутриcase_block. - В противном случае предпринимается попытка сопоставления со следующим
case_block, как описано выше. - Если блоков case больше нет, выполнение инструкции match завершается.
- Если условие вычисляется как истинное или отсутствует, выполняется
Примечание
Как правило, пользователям не следует полагаться на то, что образец будет вычислен. В зависимости от реализации интерпретатор может кэшировать значения или применять другие оптимизации, пропускающие повторные вычисления.
Пример инструкции 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" assignment_expression
Условие guard (входящее в состав case) должно выполниться, чтобы код внутри блока case был запущен. Оно имеет вид: if, за которым следует выражение.
Логический поток выполнения блока case с guard выглядит следующим образом:
- Проверяется, успешно ли сопоставился образец в блоке
case. Если образец не сопоставился, условиеguardне вычисляется, а проверяется следующий блокcase. -
Если образец сопоставился, вычисляется
guard.- Если условие
guardвычисляется как истинное, выбирается блок case. - Если условие
guardвычисляется как ложное, блок case не выбирается. - Если при вычислении
guardвозникает исключение, оно передаётся дальше.
- Если условие
Поскольку условия являются выражениями, они могут иметь побочные эффекты. Условия должны вычисляться по порядку, от первого блока case до последнего, по одному за раз, при этом пропускаются блоки case, в которых не все образцы успешно сопоставились. (То есть условия должны вычисляться по порядку.) Вычисление условий должно прекратиться, как только будет выбран блок case.
8.6.3. Неопровержимые блоки case
Неопровержимый блок case — это блок case, который подходит для любого случая. Инструкция match может содержать не более одного неопровержимого блока case, и он должен быть последним.
Блок case считается неопровержимым, если в нём нет условия, а его образец является неопровержимым. Образец считается неопровержимым, если по одному лишь его синтаксису можно доказать, что он всегда будет успешно сопоставляться. Неопровержимыми являются только следующие образцы:
- Образцы AS, левая часть которых неопровержима
- Образцы OR, содержащие хотя бы один неопровержимый образец
- Образцы захвата
- Шаблонные образцы
- неопровержимые образцы в скобках
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 состоит из двух или более образцов, разделённых вертикальными чертами |. Синтаксис:
or_pattern: "|".closed_pattern+
Только последний подобразец может быть неопровержимым, и каждый подобразец должен связывать один и тот же набор имён во избежание неоднозначности.
Образец OR по очереди сопоставляет каждый свой подобразец со значением субъекта, пока один из них не сопоставится успешно. В этом случае образец OR считается успешно сопоставившимся. Если ни один из подобразцов не сопоставился успешно, образец OR считается не сопоставившимся.
Простыми словами, P1 | P2 | ... попытается сопоставить P1, а если это не удастся — попробует сопоставить P2; образец считается успешно сопоставившимся, если успешно сопоставился любой из них, иначе он считается не сопоставившимся.
8.6.4.2. Образцы AS
Образец 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. Образцы-литералы
Образец-литерал соответствует большинству литералов в Python. Синтаксис:
literal_pattern: signed_number
| signed_number "+" NUMBER
| signed_number "-" NUMBER
| strings
| "None"
| "True"
| "False"
signed_number: ["-"] NUMBER
Правило strings и токен NUMBER определены в стандартной грамматике Python. Поддерживаются строки в тройных кавычках. Поддерживаются необработанные строки и байтовые строки. f-строки и t-строки не поддерживаются.
Формы signed_number '+' NUMBER и signed_number '-' NUMBER используются для записи комплексных чисел; слева требуется действительное число, а справа — мнимое. Например, 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: '_'
В любом образце _ является мягким ключевым словом, но только внутри образцов. Как обычно, это идентификатор даже в выражениях субъекта match, guards и блоках case.
Простыми словами, _ всегда сопоставится успешно.
8.6.4.6. Образцы-значения
Образец-значение представляет именованное значение в Python. Синтаксис:
value_pattern: attr
attr: name_or_attr "." NAME
name_or_attr: attr | NAME
Составное имя в образце разрешается с использованием стандартных правил разрешения имён Python. Образец сопоставляется успешно, если найденное значение равно значению субъекта (при использовании оператора равенства ==).
Простыми словами, 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)) является группирующим образцом. Один образец в квадратных скобках (например, [3 | 4]) по-прежнему является образцом последовательности.
В образце последовательности может быть не более одного подобразца со звёздочкой. Такой подобразец может находиться в любой позиции. Если подобразца со звёздочкой нет, образец последовательности имеет фиксированную длину; в противном случае его длина переменная.
Ниже описан логический поток сопоставления образца последовательности со значением субъекта:
- Если значение субъекта не является последовательностью [2], образец последовательности не сопоставляется.
- Если значение субъекта является экземпляром
str,bytesилиbytearray, образец последовательности не сопоставляется. -
Дальнейшие шаги зависят от того, имеет ли образец последовательности фиксированную или переменную длину.
Если длина образца последовательности фиксирована:
- Если длина последовательности-субъекта не равна количеству подобразцов, образец последовательности не сопоставляется.
- Подобразцы в образце последовательности сопоставляются с соответствующими элементами последовательности-субъекта слева направо. Сопоставление прекращается, как только один из подобразцов не сопоставляется. Если все подобразцы успешно сопоставились с соответствующими элементами, образец последовательности сопоставляется успешно.
В противном случае, если длина образца последовательности переменная:
- Если длина последовательности-субъекта меньше количества подобразцов без звёздочки, образец последовательности не сопоставляется.
- Начальные подобразцы без звёздочки сопоставляются с соответствующими элементами, как и для последовательностей фиксированной длины.
- Если предыдущий шаг выполнен успешно, подобразец со звёздочкой сопоставляется со списком, сформированным из оставшихся элементов субъекта; из него исключаются конечные элементы, соответствующие подобразцам без звёздочки, следующим за подобразцом со звёздочкой.
- Оставшиеся подобразцы без звёздочки сопоставляются с соответствующими элементами субъекта, как и для последовательности фиксированной длины.
Примечание
Длина последовательности-субъекта определяется с помощью
len()(то есть посредством протокола__len__()). Интерпретатор может кэшировать эту длину аналогично образцам-значениям.
Простыми словами, [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 во время выполнения.
Ниже описан логический поток сопоставления образца отображения со значением субъекта:
- Если значение субъекта не является отображением [3], образец отображения не сопоставляется.
- Если в отображении-субъекте присутствуют все ключи, заданные в образце отображения, а образец для каждого ключа сопоставляется с соответствующим элементом отображения-субъекта, образец отображения сопоставляется успешно.
- Если в образце отображения обнаружены повторяющиеся ключи, образец считается недопустимым. Для повторяющихся значений-литералов вызывается исключение
SyntaxError; для именованных ключей с одинаковым значением — исключениеValueError.
Примечание
Пары «ключ-значение» сопоставляются с помощью двухаргументной формы метода get() отображения-субъекта. Сопоставляемые пары «ключ-значение» должны уже присутствовать в отображении, а не создаваться на лету с помощью __missing__() или __getitem__().
Простыми словами, {KEY1: P1, KEY2: P2, ... } сопоставляется успешно, только если выполнены все следующие условия:
- проверить, что
<subject>является отображением KEY1 in <subject>-
P1сопоставляется с<subject>[KEY1] - … и так далее для соответствующих пар КЛЮЧ/образец.
8.6.4.10. Образцы классов
Образец класса представляет класс и его позиционные и именованные аргументы (если они есть). Синтаксис:
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. - Если значение субъекта не является экземпляром
name_or_attr(проверка выполняется с помощьюisinstance()), образец класса не сопоставляется. -
Если аргументы образца отсутствуют, сопоставление завершается успешно. В противном случае дальнейшие шаги зависят от наличия образцов именованных или позиционных аргументов.
Для некоторых встроенных типов (перечисленных ниже) допускается один позиционный подобразец, который сопоставляется со всем субъектом; для этих типов также работают именованные образцы, как и для остальных типов.
Если присутствуют только именованные образцы, они обрабатываются по очереди следующим образом:
-
Ключевое слово ищется как атрибут субъекта.
- Если при этом вызывается исключение, отличное от
AttributeError, оно передаётся дальше. - Если при этом вызывается исключение
AttributeError, сопоставление с образцом класса считается неудачным. - В противном случае подобразец, связанный с именованным образцом, сопоставляется со значением соответствующего атрибута субъекта. Если сопоставление не удалось, образец класса не сопоставляется; если удалось, проверяется следующее ключевое слово.
- Если при этом вызывается исключение, отличное от
- Если все именованные образцы сопоставились успешно, образец класса сопоставляется успешно.
Если присутствуют позиционные образцы, перед сопоставлением они преобразуются в именованные образцы с помощью атрибута
__match_args__классаname_or_attr:-
Вызывается эквивалент
getattr(cls, "__match_args__", ()).- Если при этом вызывается исключение, оно передаётся дальше.
- Если возвращённое значение не является кортежем, преобразование завершается неудачно и вызывается исключение
TypeError. - Если позиционных образцов больше, чем
len(cls.__match_args__), вызывается исключениеTypeError. - Позиционный образец
iпреобразуется в именованный образец с использованием__match_args__[i]в качестве ключевого слова.__match_args__[i]должно быть строкой; в противном случае вызывается исключениеTypeError. - Если есть повторяющиеся ключевые слова, вызывается исключение
TypeError.
- После преобразования всех позиционных образцов в именованные сопоставление продолжается так, как если бы присутствовали только именованные образцы.
Для следующих встроенных типов обработка позиционных подобразцов отличается:
Эти классы принимают один позиционный аргумент, и соответствующий образец сопоставляется со всем объектом, а не с атрибутом. Например,
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 [type_params] "(" [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: "*" [star_parameter] ("," defparameter)* ["," [parameter_star_kwargs]] | "*" ("," defparameter)+ ["," [parameter_star_kwargs]] | parameter_star_kwargs parameter_star_kwargs: "**" parameter [","] parameter: identifier [":" expression] star_parameter: identifier [":" ["*"] expression] defparameter: parameter ["=" expression] funcname: identifier
Определение функции является исполняемой инструкцией. При её выполнении имя функции в текущем локальном пространстве имён связывается с объектом функции (обёрткой вокруг исполняемого кода функции). Этот объект функции содержит ссылку на текущее глобальное пространство имён, которое будет использоваться при вызове функции.
Определение функции не выполняет тело функции; оно выполняется только при вызове функции. [4]
Определение функции может быть обёрнуто одним или несколькими выражениями декоратора. Выражения декораторов вычисляются при определении функции, в области видимости, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращённое значение связывается с именем функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код
@f1(arg) @f2 def func(): pass
примерно эквивалентен
def func(): pass func = f1(arg)(f2(func))
за исключением того, что исходная функция временно не связывается с именем func.
Изменено в версии 3.9: Функции можно декорировать любым допустимым выражением assignment_expression. Ранее грамматика была гораздо более ограничительной; подробности см. в PEP 614.
Список параметров типа можно указать в квадратных скобках между именем функции и открывающей скобкой списка её параметров. Это указывает средствам статической проверки типов, что функция является обобщённой. Во время выполнения параметры типа можно получить из атрибута функции __type_params__. Подробнее см. в разделе Обобщённые функции.
Изменено в версии 3.12: Списки параметров типа появились в Python 3.12.
Если один или несколько параметров имеют форму параметр = выражение, у функции есть «значения параметров по умолчанию». Для параметра со значением по умолчанию соответствующий аргумент можно опустить при вызове; в этом случае вместо него подставляется значение параметра по умолчанию. Если у параметра есть значение по умолчанию, все последующие параметры вплоть до «*» также должны иметь значения по умолчанию — это синтаксическое ограничение, не выраженное в грамматике.
Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции. Это означает, что выражение вычисляется один раз при определении функции и что при каждом вызове используется одно и то же «предварительно вычисленное» значение. Особенно важно помнить об этом, если значение параметра по умолчанию — изменяемый объект, например список или словарь: если функция изменяет этот объект (например, добавляет элемент в список), фактически изменяется и значение параметра по умолчанию. Обычно это не то, что предполагалось. Этого можно избежать, используя 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.
У параметров может быть аннотация вида «: expression», следующая за именем параметра. Аннотацию можно указать для любого параметра, в том числе для параметров вида *identifier или **identifier. (В особом случае параметры вида *identifier могут иметь аннотацию «: *expression».) После списка параметров функции может быть указана аннотация «возвращаемого значения» вида «-> expression». Эти аннотации могут быть любыми допустимыми выражениями Python. Наличие аннотаций не меняет семантику функции. Дополнительные сведения об аннотациях см. в разделе Аннотации.
Изменено в версии 3.11: Параметры вида «*identifier» могут иметь аннотацию «: *expression». См. PEP 646.
Также можно создавать анонимные функции (функции, не связанные с именем) для непосредственного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе Лямбда-выражения. Обратите внимание: лямбда-выражение — это лишь сокращённая форма упрощённого определения функции; функцию, определённую в инструкции «def», можно передавать или присваивать другому имени так же, как функцию, определённую лямбда-выражением. Форма «def» на самом деле мощнее, поскольку позволяет выполнять несколько инструкций и использовать аннотации.
Примечание для программистов: Функции являются объектами первого класса. Инструкция «def», выполненная внутри определения функции, определяет локальную функцию, которую можно вернуть или передать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным содержащей её функции. Подробности см. в разделе Имена и связывание.
См. также
- PEP 3107 — Аннотации функций
-
Исходная спецификация аннотаций функций.
- PEP 484 — Подсказки типов
-
Определение стандартного значения аннотаций: подсказки типов.
- PEP 526 — Синтаксис аннотаций переменных
-
Возможность указывать подсказки типов для объявлений переменных, в том числе переменных класса и экземпляра.
- PEP 563 — Отложенное вычисление аннотаций
-
Поддержка прямых ссылок в аннотациях: во время выполнения аннотации сохраняются в виде строк, а не вычисляются сразу.
- PEP 318 — Декораторы функций и методов
-
Были добавлены декораторы функций и методов. Декораторы классов были добавлены в PEP 3129.
8.8. Определения классов
Определение класса определяет объект класса (см. раздел Стандартная иерархия типов):
classdef: [decorators] "class" classname [type_params] [inheritance] ":" suite inheritance: "(" [argument_list] ")" classname: identifier
Определение класса является исполняемой инструкцией. Список наследования обычно содержит список базовых классов (о более сложных вариантах использования см. раздел Метаклассы), поэтому каждый элемент списка должен вычисляться в объект класса, допускающий создание подклассов. Классы без списка наследования по умолчанию наследуются от базового класса object; следовательно,
class Foo:
pass
эквивалентно
class Foo(object):
pass
Затем блок класса выполняется в новом кадре выполнения (см. раздел Имена и связывание) с использованием вновь созданного локального пространства имён и исходного глобального пространства имён. (Обычно блок состоит преимущественно из определений функций.) После завершения выполнения блока класса его кадр выполнения удаляется, но локальное пространство имён сохраняется. [5] Затем создаётся объект класса: для базовых классов используется список наследования, а для словаря атрибутов — сохранённое локальное пространство имён. Имя класса связывается с этим объектом класса в исходном локальном пространстве имён.
Порядок определения атрибутов в теле класса сохраняется в атрибуте нового класса __dict__. Обратите внимание, что это гарантируется только сразу после создания класса и только для классов, определённых с помощью синтаксиса определений.
Создание классов можно в значительной степени настраивать с помощью метаклассов.
Классы также можно декорировать: так же, как и при декорировании функций,
@f1(arg) @f2 class Foo: pass
примерно эквивалентно
class Foo: pass Foo = f1(arg)(f2(Foo))
Правила вычисления выражений декораторов такие же, как для декораторов функций. Результат затем связывается с именем класса.
Изменено в версии 3.9: Классы можно декорировать любым допустимым выражением assignment_expression. Ранее грамматика была гораздо более ограничительной; подробности см. в PEP 614.
Список параметров типа можно указать в квадратных скобках сразу после имени класса. Это указывает средствам статической проверки типов, что класс является обобщённым. Во время выполнения параметры типа можно получить из атрибута класса __type_params__. Подробнее см. в разделе Обобщённые классы.
Изменено в версии 3.12: Списки параметров типа появились в Python 3.12.
Примечание для программистов: Переменные, определённые в определении класса, являются атрибутами класса; они общие для его экземпляров. Атрибуты экземпляра можно задавать в методе с помощью self.name = value. К атрибутам класса и экземпляра можно обращаться через запись «self.name»; при таком обращении атрибут экземпляра скрывает одноимённый атрибут класса. Атрибуты класса можно использовать как значения по умолчанию для атрибутов экземпляра, но использование там изменяемых значений может привести к неожиданным результатам. Дескрипторы можно использовать для создания переменных экземпляра с другими особенностями реализации.
См. также
8.9. Сопрограммы
Добавлено в версии 3.5.
8.9.1. Определение функции-сопрограммы
async_funcdef: [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
Выполнение сопрограмм Python можно приостанавливать и возобновлять во многих точках (см. сопрограмма). Выражения await, async for и async with можно использовать только в теле функции-сопрограммы.
Функции, определённые с помощью синтаксиса async def, всегда являются функциями-сопрограммами, даже если они не содержат ключевых слов await или async.
Использование выражения yield from внутри тела функции-сопрограммы приводит к ошибке SyntaxError.
Пример функции-сопрограммы:
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
Асинхронный итерируемый объект предоставляет метод __aiter__, который непосредственно возвращает асинхронный итератор; тот может вызывать асинхронный код в своём методе __anext__.
Инструкция async for позволяет удобно перебирать асинхронные итерируемые объекты.
Следующий код:
async for TARGET in ITER:
SUITE
else:
SUITE2
Семантически эквивалентен:
iter = (ITER).__aiter__()
running = True
while running:
try:
TARGET = await iter.__anext__()
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
за исключением того, что для __aiter__() и __anext__() используется неявный поиск специального метода.
Использование инструкции async for вне тела функции-сопрограммы приводит к ошибке SyntaxError.
8.9.3. Инструкция async with
async_with_stmt: "async" with_stmt
Асинхронный менеджер контекста — это менеджер контекста, который может приостанавливать выполнение в своих методах enter и exit.
Следующий код:
async with EXPRESSION as TARGET:
SUITE
семантически эквивалентен:
manager = (EXPRESSION)
aenter = manager.__aenter__
aexit = manager.__aexit__
value = await aenter()
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(*sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(None, None, None)
за исключением того, что для __aenter__() и __aexit__() используется неявный поиск специального метода.
Использование инструкции async with вне тела функции-сопрограммы приводит к ошибке SyntaxError.
См. также
- PEP 492 — Сопрограммы с синтаксисом async и await
-
Предложение, которое ввело сопрограммы в Python как полноценную самостоятельную концепцию и добавило соответствующий синтаксис.
8.10. Списки параметров типа
Добавлено в версии 3.12.
Изменено в версии 3.13: Добавлена поддержка значений по умолчанию (см. PEP 696).
type_params: "[" type_param ("," type_param)* "]" type_param: typevar | typevartuple | paramspec typevar: identifier (":" expression)? ("=" expression)? typevartuple: "*" identifier ("=" expression)? paramspec: "**" identifier ("=" expression)?
Функции (включая сопрограммы), классы и псевдонимы типов могут содержать список параметров типа:
def max[T](args: list[T]) -> T:
...
async def amax[T](args: list[T]) -> T:
...
class Bag[T]:
def __iter__(self) -> Iterator[T]:
...
def add(self, arg: T) -> None:
...
type ListOrSet[T] = list[T] | set[T]
Семантически это означает, что функция, класс или псевдоним типа обобщены по переменной типа. Эти сведения используются преимущественно средствами статической проверки типов; во время выполнения обобщённые объекты ведут себя почти так же, как их необобщённые аналоги.
Параметры типа объявляются в квадратных скобках ([]) сразу после имени функции, класса или псевдонима типа. Параметры типа доступны в области видимости обобщённого объекта, но не за её пределами. Поэтому после объявления def func[T](): pass имя T недоступно в области видимости модуля. Далее семантика обобщённых объектов описывается точнее. Область видимости параметров типа моделируется специальной функцией (технически — областью видимости аннотаций), которая оборачивает создание обобщённого объекта.
У обобщённых функций, классов и псевдонимов типов есть атрибут __type_params__, содержащий список их параметров типа.
Существует три вида параметров типа:
-
typing.TypeVar, вводимый обычным именем (например,T). Семантически для средства проверки типов он представляет один тип. -
typing.TypeVarTuple, вводимый именем с одной звёздочкой в начале (например,*Ts). Семантически он представляет кортеж из произвольного количества типов. -
typing.ParamSpec, вводимый именем с двумя звёздочками в начале (например,**P). Семантически он представляет параметры вызываемого объекта.
Объявления typing.TypeVar могут задавать границы и ограничения: после двоеточия (:) указывается выражение. Одно выражение после двоеточия задаёт границу (например, T: int). Семантически это означает, что typing.TypeVar может представлять только типы, являющиеся подтипами этой границы. Кортеж выражений в скобках после двоеточия задаёт набор ограничений (например, T: (str, bytes)). Каждый элемент кортежа должен быть типом (это также не проверяется во время выполнения). Переменные типа с ограничениями могут принимать только один из типов в списке ограничений.
Для typing.TypeVar, объявленных с помощью синтаксиса списка параметров типа, граница и ограничения вычисляются не при создании обобщённого объекта, а только при явном обращении к атрибутам __bound__ и __constraints__. Для этого границы и ограничения вычисляются в отдельной области видимости аннотаций.
У typing.TypeVarTuple и typing.ParamSpec не может быть границ или ограничений.
Все три вида параметров типа также могут иметь значение по умолчанию, которое используется, если параметр типа не указан явно. Оно задаётся добавлением одного знака равенства (=), за которым следует выражение. Как и границы и ограничения переменных типа, значение по умолчанию вычисляется не при создании объекта, а только при обращении к атрибуту __default__ параметра типа. Для этого значение по умолчанию вычисляется в отдельной области видимости аннотаций. Если для параметра типа не указано значение по умолчанию, атрибуту __default__ присваивается специальный объект-маркер typing.NoDefault.
В следующем примере показан полный набор допустимых объявлений параметров типа:
def overly_generic[ SimpleTypeVar, TypeVarWithDefault = int, TypeVarWithBound: int, TypeVarWithConstraints: (str, bytes), *SimpleTypeVarTuple = (int, float), **SimpleParamSpec = (str, bytearray), ]( a: SimpleTypeVar, b: TypeVarWithDefault, c: TypeVarWithBound, d: Callable[SimpleParamSpec, TypeVarWithConstraints], *e: SimpleTypeVarTuple, ): ...
8.10.1. Обобщённые функции
Обобщённые функции объявляются следующим образом:
def func[T](arg: T): ...
Этот синтаксис эквивалентен:
annotation-def TYPE_PARAMS_OF_func():
T = typing.TypeVar("T")
def func(arg: T): ...
func.__type_params__ = (T,)
return func
func = TYPE_PARAMS_OF_func()
Здесь annotation-def обозначает область видимости аннотаций, которая фактически не связывается ни с одним именем во время выполнения. (При преобразовании также допущено одно упрощение: синтаксис не обращается к атрибуту модуля typing, а непосредственно создаёт экземпляр typing.TypeVar.)
Аннотации обобщённых функций вычисляются в области видимости аннотаций, используемой для объявления параметров типа, однако значения параметров по умолчанию и декораторы функции в этой области не вычисляются.
Следующий пример иллюстрирует правила области видимости для этих случаев, а также для дополнительных видов параметров типа:
@decorator
def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):
...
За исключением ленивого вычисления границы TypeVar, это эквивалентно:
DEFAULT_OF_arg = some_default
annotation-def TYPE_PARAMS_OF_func():
annotation-def BOUND_OF_T():
return int
# In reality, BOUND_OF_T() is evaluated only on demand.
T = typing.TypeVar("T", bound=BOUND_OF_T())
Ts = typing.TypeVarTuple("Ts")
P = typing.ParamSpec("P")
def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):
...
func.__type_params__ = (T, Ts, P)
return func
func = decorator(TYPE_PARAMS_OF_func())
Имена с заглавной буквы, такие как DEFAULT_OF_arg, фактически не связываются во время выполнения.
8.10.2. Обобщённые классы
Обобщённые классы объявляются следующим образом:
class Bag[T]: ...
Этот синтаксис эквивалентен:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(typing.Generic[T]):
__type_params__ = (T,)
...
return Bag
Bag = TYPE_PARAMS_OF_Bag()
И здесь annotation-def (не настоящее ключевое слово) обозначает область видимости аннотаций, а имя TYPE_PARAMS_OF_Bag фактически не связывается во время выполнения.
Обобщённые классы неявно наследуются от typing.Generic. Базовые классы и именованные аргументы обобщённых классов вычисляются в области видимости типов для параметров типа, а декораторы вычисляются вне этой области. Это показано в следующем примере:
@decorator class Bag(Base[T], arg=T): ...
Это эквивалентно:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(Base[T], typing.Generic[T], arg=T):
__type_params__ = (T,)
...
return Bag
Bag = decorator(TYPE_PARAMS_OF_Bag())
8.10.3. Обобщённые псевдонимы типов
Инструкцию type также можно использовать для создания обобщённого псевдонима типа:
type ListOrSet[T] = list[T] | set[T]
За исключением ленивого вычисления значения, это эквивалентно:
annotation-def TYPE_PARAMS_OF_ListOrSet():
T = typing.TypeVar("T")
annotation-def VALUE_OF_ListOrSet():
return list[T] | set[T]
# In reality, the value is lazily evaluated
return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))
ListOrSet = TYPE_PARAMS_OF_ListOrSet()
Здесь annotation-def (не настоящее ключевое слово) обозначает область видимости аннотаций. Имена с заглавной буквы, такие как TYPE_PARAMS_OF_ListOrSet, фактически не связываются во время выполнения.
8.11. Аннотации
Изменено в версии 3.14: Теперь аннотации по умолчанию вычисляются отложенно.
Переменные и параметры функций могут иметь аннотации, которые создаются добавлением двоеточия после имени с последующим выражением:
x: annotation = 1 def f(param: annotation): ...
Функции также могут иметь аннотацию возвращаемого значения, следующую за стрелкой:
def f() -> annotation: ...
Аннотации обычно используются для подсказок типов, однако язык не требует этого, и в целом аннотации могут содержать произвольные выражения. Наличие аннотаций не меняет семантику выполнения кода, за исключением случаев, когда используется механизм, который анализирует аннотации и применяет их (например, dataclasses или @functools.singledispatch).
По умолчанию аннотации отложенно вычисляются в области видимости аннотаций. Это означает, что они не вычисляются при вычислении кода, содержащего аннотацию. Вместо этого интерпретатор сохраняет сведения, которые можно использовать для вычисления аннотации позднее, если это потребуется. Модуль annotationlib предоставляет инструменты для вычисления аннотаций.
Если присутствует инструкция future from __future__ import annotations, все аннотации вместо этого сохраняются в виде строк:
>>> from __future__ import annotations
>>> def f(param: annotation): ...
>>> f.__annotations__
{'param': 'annotation'}
Эта инструкция future будет объявлена устаревшей и удалена в будущей версии Python, но не ранее окончания срока поддержки Python 3.13 (см. PEP 749). При её использовании средства интроспекции, такие как annotationlib.get_annotations() и typing.get_type_hints(), с меньшей вероятностью смогут разрешить аннотации во время выполнения.
Сноски
© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/reference/compound_stmts.html