Spec-Zone.ru › Python 3.14

Составные инструкции

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

Инструкции 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 с одним «элементом» происходит следующим образом:

  1. Вычисляется выражение контекста (выражение, указанное в with_item), чтобы получить менеджер контекста.
  2. Для последующего использования загружается метод __enter__() менеджера контекста.
  3. Для последующего использования загружается метод __exit__() менеджера контекста.
  4. Вызывается метод __enter__() менеджера контекста.
  5. Если в инструкции with указана цель, ей присваивается возвращаемое значение __enter__().

    Примечание

    Инструкция with гарантирует, что если метод __enter__() завершится без ошибки, то __exit__() будет вызван всегда. Поэтому ошибка при присваивании целевому списку будет обработана так же, как ошибка, возникшая внутри блока. См. шаг 7 ниже.

  6. Выполняется блок.
  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: Добавлена поддержка группирующих скобок для переноса инструкции на несколько строк.

См. также

PEP 343 — Инструкция «with»

Спецификация, предыстория и примеры инструкции with в Python.

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 являются мягкими ключевыми словами.

См. также

  • PEP 634 – Структурное сопоставление с образцом: спецификация
  • PEP 636 – Структурное сопоставление с образцом: руководство

8.6.1. Обзор

Ниже представлен обзор логического потока выполнения инструкции match:

  1. Вычисляется выражение субъекта subject_expr и получается результирующее значение субъекта. Если выражение субъекта содержит запятую, кортеж создаётся в соответствии с стандартными правилами.
  2. Каждый образец в case_block по очереди пытаются сопоставить со значением субъекта. Конкретные правила успешного или неуспешного сопоставления описаны ниже. При попытке сопоставления также может быть выполнена привязка некоторых или всех отдельных имён в образце. Точные правила привязки образцов различаются в зависимости от типа образца и приведены ниже. Имена, привязанные при успешном сопоставлении с образцом, остаются доступны после выполнения блока и могут использоваться после инструкции match.

    Примечание

    При неудачном сопоставлении с образцом некоторые подобразцы могут успешно сопоставиться. Не полагайтесь на то, что при неудачном сопоставлении будут выполнены привязки. И наоборот, не полагайтесь на то, что после неудачного сопоставления переменные останутся неизменными. Точное поведение зависит от реализации и может различаться. Такое решение принято намеренно, чтобы разные реализации могли добавлять оптимизации.

  3. Если образец успешно сопоставился, вычисляется соответствующее условие (если оно есть). В этом случае гарантируется, что все привязки имён уже выполнены.

    • Если условие вычисляется как истинное или отсутствует, выполняется 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 выглядит следующим образом:

  1. Проверяется, успешно ли сопоставился образец в блоке case. Если образец не сопоставился, условие guard не вычисляется, а проверяется следующий блок case.
  2. Если образец сопоставился, вычисляется 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]) по-прежнему является образцом последовательности.

В образце последовательности может быть не более одного подобразца со звёздочкой. Такой подобразец может находиться в любой позиции. Если подобразца со звёздочкой нет, образец последовательности имеет фиксированную длину; в противном случае его длина переменная.

Ниже описан логический поток сопоставления образца последовательности со значением субъекта:

  1. Если значение субъекта не является последовательностью [2], образец последовательности не сопоставляется.
  2. Если значение субъекта является экземпляром str, bytes или bytearray, образец последовательности не сопоставляется.
  3. Дальнейшие шаги зависят от того, имеет ли образец последовательности фиксированную или переменную длину.

    Если длина образца последовательности фиксирована:

    1. Если длина последовательности-субъекта не равна количеству подобразцов, образец последовательности не сопоставляется.
    2. Подобразцы в образце последовательности сопоставляются с соответствующими элементами последовательности-субъекта слева направо. Сопоставление прекращается, как только один из подобразцов не сопоставляется. Если все подобразцы успешно сопоставились с соответствующими элементами, образец последовательности сопоставляется успешно.

    В противном случае, если длина образца последовательности переменная:

    1. Если длина последовательности-субъекта меньше количества подобразцов без звёздочки, образец последовательности не сопоставляется.
    2. Начальные подобразцы без звёздочки сопоставляются с соответствующими элементами, как и для последовательностей фиксированной длины.
    3. Если предыдущий шаг выполнен успешно, подобразец со звёздочкой сопоставляется со списком, сформированным из оставшихся элементов субъекта; из него исключаются конечные элементы, соответствующие подобразцам без звёздочки, следующим за подобразцом со звёздочкой.
    4. Оставшиеся подобразцы без звёздочки сопоставляются с соответствующими элементами субъекта, как и для последовательности фиксированной длины.

    Примечание

    Длина последовательности-субъекта определяется с помощью 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 во время выполнения.

Ниже описан логический поток сопоставления образца отображения со значением субъекта:

  1. Если значение субъекта не является отображением [3], образец отображения не сопоставляется.
  2. Если в отображении-субъекте присутствуют все ключи, заданные в образце отображения, а образец для каждого ключа сопоставляется с соответствующим элементом отображения-субъекта, образец отображения сопоставляется успешно.
  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

В образцах классов нельзя повторять одно и то же ключевое слово.

Ниже описан логический поток сопоставления образца класса со значением субъекта:

  1. Если name_or_attr не является экземпляром встроенного типа type, вызывается исключение TypeError.
  2. Если значение субъекта не является экземпляром name_or_attr (проверка выполняется с помощью isinstance()), образец класса не сопоставляется.
  3. Если аргументы образца отсутствуют, сопоставление завершается успешно. В противном случае дальнейшие шаги зависят от наличия образцов именованных или позиционных аргументов.

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

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

    1. Ключевое слово ищется как атрибут субъекта.

      • Если при этом вызывается исключение, отличное от AttributeError, оно передаётся дальше.
      • Если при этом вызывается исключение AttributeError, сопоставление с образцом класса считается неудачным.
      • В противном случае подобразец, связанный с именованным образцом, сопоставляется со значением соответствующего атрибута субъекта. Если сопоставление не удалось, образец класса не сопоставляется; если удалось, проверяется следующее ключевое слово.
    2. Если все именованные образцы сопоставились успешно, образец класса сопоставляется успешно.

    Если присутствуют позиционные образцы, перед сопоставлением они преобразуются в именованные образцы с помощью атрибута __match_args__ класса name_or_attr:

    1. Вызывается эквивалент getattr(cls, "__match_args__", ()).

      • Если при этом вызывается исключение, оно передаётся дальше.
      • Если возвращённое значение не является кортежем, преобразование завершается неудачно и вызывается исключение TypeError.
      • Если позиционных образцов больше, чем len(cls.__match_args__), вызывается исключение TypeError.
      • Позиционный образец i преобразуется в именованный образец с использованием __match_args__[i] в качестве ключевого слова. __match_args__[i] должно быть строкой; в противном случае вызывается исключение TypeError.
      • Если есть повторяющиеся ключевые слова, вызывается исключение TypeError.

      См. также

      Настройка позиционных аргументов при сопоставлении с образцом класса

    2. После преобразования всех позиционных образцов в именованные сопоставление продолжается так, как если бы присутствовали только именованные образцы.

    Для следующих встроенных типов обработка позиционных подобразцов отличается:

    • bool
    • bytearray
    • bytes
    • dict
    • float
    • frozenset
    • int
    • list
    • set
    • str
    • tuple

    Эти классы принимают один позиционный аргумент, и соответствующий образец сопоставляется со всем объектом, а не с атрибутом. Например, 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
  • … и так далее для каждой соответствующей пары именованный аргумент/образец.

См. также

  • PEP 634 – Структурное сопоставление с образцом: спецификация
  • PEP 636 – Структурное сопоставление с образцом: руководство

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»; при таком обращении атрибут экземпляра скрывает одноимённый атрибут класса. Атрибуты класса можно использовать как значения по умолчанию для атрибутов экземпляра, но использование там изменяемых значений может привести к неожиданным результатам. Дескрипторы можно использовать для создания переменных экземпляра с другими особенностями реализации.

См. также

PEP 3115 — Метаклассы в Python 3000

Предложение, изменившее объявление метаклассов на текущий синтаксис и определившее семантику создания классов с метаклассами.

PEP 3129 — Декораторы классов

Предложение, добавившее декораторы классов. Декораторы функций и методов были добавлены в PEP 318.

8.9. Сопрограммы

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

8.9.1. Определение функции-сопрограммы

async_funcdef: [decorators] "async" "def" funcname "(" [parameter_list] ")"
               ["->" expression] ":" suite

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

Сноски

[1]

Исключение передаётся в стек вызовов, если только нет предложения finally, которое, в свою очередь, вызывает другое исключение. Новое исключение приводит к потере старого.

[2]

При сопоставлении с образцом последовательность определяется как один из следующих вариантов:

  • класс, наследующий от collections.abc.Sequence
  • класс Python, зарегистрированный как collections.abc.Sequence
  • встроенный класс, у которого установлен бит (CPython) Py_TPFLAGS_SEQUENCE
  • класс, наследующий от любого из перечисленных выше

Следующие классы стандартной библиотеки являются последовательностями:

  • array.array
  • collections.deque
  • list
  • memoryview
  • range
  • tuple

Примечание

Значения subject типа str, bytes и bytearray не соответствуют образцам последовательностей.

[3]

При сопоставлении с образцом отображение определяется как один из следующих вариантов:

  • класс, наследующий от collections.abc.Mapping
  • класс Python, зарегистрированный как collections.abc.Mapping
  • встроенный класс, у которого установлен бит (CPython) Py_TPFLAGS_MAPPING
  • класс, наследующий от любого из перечисленных выше

Классы стандартной библиотеки dict и types.MappingProxyType являются отображениями.

[4]

Строковый литерал, стоящий первым оператором в теле функции, преобразуется в атрибут __doc__ функции и, следовательно, становится её строкой документации.

[5]

Строковый литерал, стоящий первым оператором в теле класса, преобразуется в элемент __doc__ пространства имён и, следовательно, становится строкой документации класса.

© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/reference/compound_stmts.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API