Составные инструкции
Составные инструкции содержат другие инструкции (или их группы); они тем или иным образом влияют на выполнение этих инструкций или управляют им. Как правило, составные инструкции занимают несколько строк, хотя в простых случаях целая составная инструкция может уместиться в одной строке.
Инструкции 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_list ":" suite
["else" ":" suite]
Выражение starred_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.
8.4.1. Часть except
Часть или части except задают один или несколько обработчиков исключений. Если в части try исключение не возникает, обработчики исключений не выполняются. Если исключение возникает в блоке try, начинается поиск обработчика исключений. При поиске по очереди проверяются части except, пока не будет найдена подходящая исключению. Часть except без выражения, если она присутствует, должна быть последней; она подходит для любого исключения.
В части except с выражением это выражение должно вычисляться в тип исключения или кортеж типов исключений. Возникшее исключение соответствует части 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, но сопоставление выполняется с исключениями, содержащимися в обрабатываемой группе. Возникает исключение TypeError, если сопоставляемый тип является подклассом BaseExceptionGroup, поскольку это привело бы к неоднозначной семантике.
Когда в блоке 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, сохранённое исключение отбрасывается:
>>> 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 используется для обёртывания выполнения блока методами, определёнными менеджером контекста (см. раздел Менеджеры контекста инструкции 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 = 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 INDENT case_block+ DEDENT subject_expr ::=star_named_expression","star_named_expressions? |named_expressioncase_block ::= 'case' patterns [guard] ":"block
Примечание
В этом разделе для обозначения мягких ключевых слов используются одинарные кавычки.
Сопоставление с образцом принимает образец в качестве входных данных (следующий за 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" named_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-строки не поддерживаются.
Формы 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, guard и блоках 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()), образец класса считается неуспешным. -
Если аргументы образца отсутствуют, образец считается успешным. В противном случае дальнейшие шаги зависят от наличия образцов именованных или позиционных аргументов.
Для ряда встроенных типов, перечисленных ниже, допускается один позиционный подобразец, который сопоставляется со всем субъектом; для этих типов также работают именованные образцы, как и для других типов.
Если присутствуют только именованные образцы, они обрабатываются по очереди следующим образом:
I. Именованный аргумент ищется как атрибут субъекта.
- Если при этом возникает исключение, отличное от
AttributeError, оно передаётся выше. - Если при этом возникает
AttributeError, образец класса считается неуспешным. - В противном случае подобразец, связанный с именованным образцом, сопоставляется со значением атрибута субъекта. Если это не удаётся, образец класса считается неуспешным; если удаётся, сопоставление переходит к следующему именованному аргументу.
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 [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. Наличие аннотаций не меняет семантику функции. Значения аннотаций доступны в виде значений словаря, ключами которого являются имена параметров, в атрибуте __annotations__ объекта-функции. Если используется импорт annotations из __future__, во время выполнения аннотации сохраняются в виде строк, что позволяет отложить их вычисление. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут вычисляться в порядке, отличном от порядка их появления в исходном коде.
Изменено в версии 3.11: У параметров вида «*identifier» может быть аннотация «: *expression». См. PEP 646.
Также можно создавать анонимные функции (функции, не связанные с именем) для непосредственного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе Лямбда-выражения. Обратите внимание, что лямбда-выражение — лишь сокращённая форма упрощённого определения функции; функцию, определённую в инструкции «def», можно передавать или присваивать другому имени так же, как функцию, определённую с помощью лямбда-выражения. Форма «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)
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__().
Использование инструкции 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 = 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__().
Использование инструкции 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, фактически не связываются во время выполнения.
Сноски
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/reference/compound_stmts.html