Документация Python неофициальный перевод

compound_stmts.md

1384 строк · 125.6 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.15/reference/compound_stmts.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 8. Составные инструкции89Составные инструкции содержат (группы) других инструкций; они влияют на выполнение этих других инструкций или управляют им. В общем случае составные инструкции охватывают несколько строк, хотя в простых вариантах вся составная инструкция может помещаться в одну строку.1011Инструкции [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if), [`while`](https://python-all.ru/3.15/reference/compound_stmts.html#while) и [`for`](https://python-all.ru/3.15/reference/compound_stmts.html#for) реализуют традиционные конструкции управления потоком. [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try) задаёт обработчики исключений и/или код очистки для группы инструкций, а инструкция [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) позволяет выполнять код инициализации и финализации вокруг блока кода. Определения функций и классов также синтаксически являются составными инструкциями.1213Составная инструкция состоит из одного или нескольких «предложений». Предложение состоит из заголовка и «набора инструкций». Заголовки предложений одной составной инструкции находятся на одном уровне отступа. Каждый заголовок предложения начинается с уникального ключевого слова и завершается двоеточием. Набор инструкций – это группа инструкций, управляемая предложением. Набор инструкций может состоять из одной или нескольких простых инструкций, разделённых точкой с запятой, на той же строке, что и заголовок, после его двоеточия, или из одной или нескольких инструкций с отступом на последующих строках. Только вторая форма набора инструкций может содержать вложенные составные инструкции; следующий пример недопустим, в основном потому, что было бы непонятно, к какому предложению [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if) будет относиться последующее предложение [`else`](https://python-all.ru/3.15/reference/compound_stmts.html#else):1415```python16if test1: if test2: print(x)17```1819Также обратите внимание, что точка с запятой связывает сильнее, чем двоеточие в этом контексте, так что в следующем примере выполняются либо все вызовы [`print()`](https://python-all.ru/3.15/library/functions.html#print), либо ни один:2021```python22if x < y < z: print(x); print(y); print(z)23```2425Подводя итог:2627```2829compound_stmt: if_stmt30               | while_stmt31               | for_stmt32               | try_stmt33               | with_stmt34               | match_stmt35               | funcdef36               | classdef37               | async_with_stmt38               | async_for_stmt39               | async_funcdef40suite:         stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT41statement:     stmt_list NEWLINE | compound_stmt42stmt_list:     simple_stmt (";" simple_stmt)* [";"]43```4445Обратите внимание, что инструкции всегда заканчиваются `NEWLINE`, за которым может следовать `DEDENT`. Также обратите внимание, что опциональные продолжения всегда начинаются с ключевого слова, которое не может начинать инструкцию, поэтому неоднозначностей нет (проблема «висячего [`else`](https://python-all.ru/3.15/reference/compound_stmts.html#else)» решается в Python требованием, чтобы вложенные инструкции [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if) имели отступ).4647Форматирование грамматических правил в следующих разделах помещает каждое предложение на отдельную строку для ясности.4849## 8.1. Инструкция `if`5051Инструкция [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if) используется для условного выполнения:5253```5455if_stmt: "if" assignment_expression ":" suite56         ("elif" assignment_expression ":" suite)*57         ["else" ":" suite]58```5960Он выбирает ровно один из наборов инструкций, вычисляя выражения одно за другим, пока одно из них не окажется истинным (см. раздел [Булевы операции](https://python-all.ru/3.15/reference/expressions.html#booleans) для определения истины и лжи); затем этот набор выполняется (и никакая другая часть инструкции [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if) не выполняется и не вычисляется). Если все выражения ложны, выполняется набор инструкций предложения [`else`](https://python-all.ru/3.15/reference/compound_stmts.html#else), если оно присутствует.6162## 8.2. Инструкция `while`6364Инструкция [`while`](https://python-all.ru/3.15/reference/compound_stmts.html#while) используется для повторного выполнения, пока выражение истинно:6566```6768while_stmt: "while" assignment_expression ":" suite69            ["else" ":" suite]70```7172Эта инструкция многократно проверяет выражение и, если оно истинно, выполняет первый набор инструкций; если выражение ложно (возможно, при первой проверке), то набор инструкций предложения `else`, если оно присутствует, выполняется, и цикл завершается.7374Инструкция [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue), выполненная в первом наборе, пропускает оставшуюся часть набора и возвращается к проверке выражения.7576## 8.3. Инструкция `for`7778Инструкция [`for`](https://python-all.ru/3.15/reference/compound_stmts.html#for) используется для перебора элементов последовательности (например, строки, кортежа или списка) или другого итерируемого объекта:7980```8182for_stmt: "for" target_list "in" starred_expression_list ":" suite83          ["else" ":" suite]84```8586Выражение [`starred_expression_list`](https://python-all.ru/3.15/reference/expressions.html#grammar-token-python-grammar-starred_expression_list) вычисляется один раз; оно должно возвращать объект [итерируемый](https://python-all.ru/3.15/glossary.html#term-iterable). Для этого итерируемого объекта создаётся [итератор](https://python-all.ru/3.15/glossary.html#term-iterator). Первый элемент, предоставленный итератором, затем присваивается целевому списку с использованием стандартных правил присваивания (см. [Инструкции присваивания](https://python-all.ru/3.15/reference/simple_stmts.html#assignment)), и набор инструкций выполняется. Это повторяется для каждого элемента, предоставленного итератором. Когда итератор исчерпан, выполняется набор инструкций в предложении `else`, если оно присутствует, и цикл завершается.8788Инструкция [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue), выполненная в первом наборе, пропускает оставшуюся часть набора и продолжает со следующим элементом, или с предложением `else`, если следующего элемента нет.8990Цикл for выполняет присваивания переменным в целевом списке. Это перезаписывает все предыдущие присваивания этим переменным, включая те, что были сделаны в наборе инструкций цикла for:9192```python93for i in range(10):94    print(i)95    i = 5             # это не повлияет на цикл for96                      # потому что i будет перезаписано следующим97                      # индексом в range98```99100Имена в целевом списке не удаляются после завершения цикла, но если последовательность пуста, они вообще не будут присвоены циклом. Подсказка: встроенный тип [`range()`](https://python-all.ru/3.15/library/stdtypes.html#range) представляет неизменяемые арифметические последовательности целых чисел. Например, перебор `range(3)` последовательно даёт 0, 1, а затем 2.101102Изменено в версии 3.11: Элементы со звёздочкой теперь разрешены в списке выражений.103104## 8.4. Инструкция `try`105106Инструкция `try` задаёт обработчики исключений и/или код очистки для группы инструкций:107108```109110try_stmt:  try1_stmt | try2_stmt | try3_stmt111try1_stmt: "try" ":" suite112           ("except" [expression ["as" identifier]] ":" suite)+113           ["else" ":" suite]114           ["finally" ":" suite]115try2_stmt: "try" ":" suite116           ("except" "*" expression ["as" identifier] ":" suite)+117           ["else" ":" suite]118           ["finally" ":" suite]119try3_stmt: "try" ":" suite120           "finally" ":" suite121```122123Дополнительную информацию об исключениях можно найти в разделе [Исключения](https://python-all.ru/3.15/reference/executionmodel.html#exceptions), а информация об использовании инструкции [`raise`](https://python-all.ru/3.15/reference/simple_stmts.html#raise) для генерации исключений приведена в разделе [Инструкция raise](https://python-all.ru/3.15/reference/simple_stmts.html#raise).124125Изменено в версии 3.14: Поддержка опционального опускания группирующих скобок при использовании нескольких типов исключений. См. [**PEP 758**](https://python-all.ru/3.15/reference/compound_stmts.html).126127### 8.4.1. `except` предложение128129Предложения `except` задают один или несколько обработчиков исключений. Если в предложении [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try) не возникает исключения, ни один обработчик не выполняется. Когда в блоке `try` возникает исключение, начинается поиск обработчика исключения. Этот поиск последовательно проверяет предложения `except`, пока не найдёт подходящее для этого исключения. Предложение `except` без выражения, если присутствует, должно быть последним; оно перехватывает любое исключение.130131Для предложения `except` с выражением это выражение должно вычисляться в тип исключения или кортеж типов исключений. Круглые скобки можно опустить, если указано несколько типов исключений и предложение `as` не используется. Вызванное исключение соответствует предложению `except`, чьё выражение вычисляется в класс или [невиртуальный базовый класс](https://python-all.ru/3.15/glossary.html#term-abstract-base-class) объекта исключения, или в кортеж, содержащий такой класс.132133Если ни одно предложение `except` не соответствует исключению, поиск обработчика исключения продолжается в окружающем коде и в стеке вызовов. [\[1\]](https://python-all.ru/3.15/reference/compound_stmts.html#id22)134135Если вычисление выражения в заголовке предложения `except` вызывает исключение, первоначальный поиск обработчика отменяется, и начинается поиск нового исключения в окружающем коде и в стеке вызовов (считается, что исключение вызвано всем оператором [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try)).136137Когда найдено подходящее предложение `except`, исключение присваивается цели, указанной после ключевого слова `as` в этом предложении `except` (если она присутствует), и выполняется блок предложения `except`. Все предложения `except` должны содержать исполняемый блок. По достижении конца этого блока выполнение продолжается нормально после всего оператора [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try). (Это означает, что если существуют два вложенных обработчика для одного и того же исключения, и исключение возникает в предложении `try` внутреннего обработчика, внешний обработчик не обработает исключение.)138139Когда исключение было присвоено с помощью `as target`, оно очищается в конце предложения `except`. Это эквивалентно следующему:140141```python142except E as N:143    foo144```145146было преобразовано в:147148```python149except E as N:150    try:151        foo152    finally:153        del N154```155156Это означает, что исключение должно быть присвоено другому имени, чтобы иметь возможность ссылаться на него после предложения `except`. Исключения очищаются, потому что вместе с прикреплённой трассировкой они образуют циклическую ссылку с кадром стека, удерживая все локальные переменные в этом кадре до следующей сборки мусора.157158Перед выполнением блока предложения `except` исключение сохраняется в модуле [`sys`](https://python-all.ru/3.15/library/sys.html#module-sys), откуда к нему можно получить доступ из тела предложения `except` с помощью вызова [`sys.exception()`](https://python-all.ru/3.15/library/sys.html#sys.exception). При выходе из обработчика исключения исключение, сохранённое в модуле `sys`, сбрасывается к предыдущему значению:159160```python161>>> print(sys.exception())162None163>>> try:164...     raise TypeError165... except:166...     print(repr(sys.exception()))167...     try:168...          raise ValueError169...     except:170...         print(repr(sys.exception()))171...     print(repr(sys.exception()))172...173TypeError()174ValueError()175TypeError()176>>> print(sys.exception())177None178```179180### 8.4.2. `except*` предложение181182Предложения `except*` задают один или несколько обработчиков для групп исключений (экземпляры [`BaseExceptionGroup`](https://python-all.ru/3.15/library/exceptions.html#BaseExceptionGroup)). Оператор [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try) может содержать либо предложения [`except`](https://python-all.ru/3.15/reference/compound_stmts.html#except), либо `except*`, но не одновременно. Тип исключения для сопоставления обязателен в случае `except*`, поэтому `except*:` является синтаксической ошибкой. Тип интерпретируется так же, как в случае `except`, но сопоставление выполняется по исключениям, содержащимся в обрабатываемой группе. Выдаётся [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError), если сопоставляемый тип является подклассом `BaseExceptionGroup`, так как это привело бы к неоднозначной семантике.183184Когда в блоке try возникает группа исключений, каждое предложение `except*` разделяет (см. [`split()`](https://python-all.ru/3.15/library/exceptions.html#BaseExceptionGroup.split)) её на подгруппы совпадающих и несовпадающих исключений. Если подгруппа совпадающих не пуста, она становится обработанным исключением (значение, возвращаемое из [`sys.exception()`](https://python-all.ru/3.15/library/sys.html#sys.exception)) и присваивается цели предложения `except*` (если такая есть). Затем выполняется тело предложения `except*`. Если подгруппа несовпадающих не пуста, она обрабатывается следующим предложением `except*` таким же образом. Это продолжается, пока все исключения в группе не будут сопоставлены или не выполнится последнее предложение `except*`.185186После выполнения всех предложений `except*` группа необработанных исключений объединяется с любыми исключениями, которые были вызваны или повторно вызваны из предложений `except*`. Эта объединённая группа исключений распространяется дальше:187188```python189>>> try:190...     raise ExceptionGroup("eg",191...         [ValueError(1), TypeError(2), OSError(3), OSError(4)])192... except* TypeError as e:193...     print(f'caught {type(e)} with nested {e.exceptions}')194... except* OSError as e:195...     print(f'caught {type(e)} with nested {e.exceptions}')196...197caught <class 'ExceptionGroup'> with nested (TypeError(2),)198caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))199  + Exception Group Traceback (most recent call last):200  |   File "<doctest default[0]>", line 2, in <module>201  |     raise ExceptionGroup("eg",202  |         [ValueError(1), TypeError(2), OSError(3), OSError(4)])203  | ExceptionGroup: eg (1 sub-exception)204  +-+---------------- 1 ----------------205    | ValueError: 1206    +------------------------------------207```208209Если исключение, вызванное в блоке [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try), не является группой исключений и его тип соответствует одному из предложений `except*`, оно перехватывается и оборачивается группой исключений с пустой строкой сообщения. Это гарантирует, что тип цели `e` всегда будет [`BaseExceptionGroup`](https://python-all.ru/3.15/library/exceptions.html#BaseExceptionGroup):210211```python212>>> try:213...     raise BlockingIOError214... except* BlockingIOError as e:215...     print(repr(e))216...217ExceptionGroup('', (BlockingIOError(),))218```219220[`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break), [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue) и [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return) не могут появляться в предложении `except*`.221222### 8.4.3. `else` предложение223224Необязательное предложение `else` выполняется, если поток управления покидает блок [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try), не было вызвано исключение и не выполнялся оператор [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return), [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue) или [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break). Исключения в предложении `else` не обрабатываются предшествующими предложениями [`except`](https://python-all.ru/3.15/reference/compound_stmts.html#except).225226### 8.4.4. `finally` предложение227228Если присутствует `finally`, он задаёт обработчик очистки. Выполняется предложение [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try), включая любые предложения [`except`](https://python-all.ru/3.15/reference/compound_stmts.html#except) и [`else`](https://python-all.ru/3.15/reference/compound_stmts.html#except-else). Если в каком-либо из предложений возникает исключение и оно не обработано, исключение временно сохраняется. Выполняется предложение `finally`. Если есть сохранённое исключение, оно повторно вызывается в конце предложения `finally`. Если предложение `finally` вызывает другое исключение, сохранённое исключение устанавливается как контекст нового исключения. Если предложение `finally` выполняет оператор [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue), сохранённое исключение отбрасывается. Например, эта функция возвращает 42.229230```python231def f():232    try:233        1/0234    finally:235        return 42236```237238Информация об исключении недоступна программе во время выполнения предложения `finally`.239240Когда оператор [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue) выполняется в блоке [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try) оператора `try``finally`, предложение `finally` также выполняется «на выходе».241242Возвращаемое значение функции определяется последним выполненным оператором [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return). Поскольку предложение `finally` выполняется всегда, оператор `return`, выполненный в предложении `finally`, всегда будет последним. Следующая функция возвращает 'finally'.243244```python245def foo():246    try:247        return 'try'248    finally:249        return 'finally'250```251252Изменено в версии 3.8: До Python 3.8 оператор [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue) был недопустим в предложении `finally` из-за проблемы в реализации.253254Изменено в версии 3.14: Компилятор выдаёт [`SyntaxWarning`](https://python-all.ru/3.15/library/exceptions.html#SyntaxWarning), когда [`return`](https://python-all.ru/3.15/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.15/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.15/reference/simple_stmts.html#continue) появляется в блоке `finally` (см. [**PEP 765**](https://python-all.ru/3.15/reference/compound_stmts.html)).255256## 8.5. Инструкция `with`257258Оператор [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) используется для обёртывания выполнения блока методами, определёнными контекстным менеджером (см. раздел [Контекстные менеджеры оператора with](https://python-all.ru/3.15/reference/datamodel.html#context-managers)). Это позволяет инкапсулировать типичные шаблоны использования [`try`](https://python-all.ru/3.15/reference/compound_stmts.html#try)…[`except`](https://python-all.ru/3.15/reference/compound_stmts.html#except)…[`finally`](https://python-all.ru/3.15/reference/compound_stmts.html#finally) для удобного повторного использования.259260```261262with_stmt:          "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite263with_stmt_contents: with_item ("," with_item)*264with_item:          expression ["as" target]265```266267Выполнение оператора [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) с одним «элементом» происходит следующим образом:2682691. Контекстное выражение (выражение, указанное в [`with_item`](https://python-all.ru/3.15/reference/compound_stmts.html#grammar-token-python-grammar-with_item)) вычисляется для получения контекстного менеджера.2702. Метод [`__enter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__enter__) контекстного менеджера загружается для последующего использования.2713. Метод [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) контекстного менеджера загружается для последующего использования.2724. Метод [`__enter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__enter__) контекстного менеджера вызывается.2735. Если в операторе [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) была указана цель, возвращаемое значение из [`__enter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__enter__) присваивается ей.274275   > **Примечание**276   >277   > Оператор [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) гарантирует, что если метод [`__enter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__enter__) возвращается без ошибки, то [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) всегда будет вызван. Таким образом, если ошибка происходит во время присваивания целевому списку, она обрабатывается так же, как ошибка, возникшая внутри блока. См. шаг 7 ниже.2786. Выполняется блок.2797. Вызывается метод [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) менеджера контекста. Если исключение вызвало выход из блока, его тип, значение и traceback передаются в качестве аргументов `__exit__()`. В противном случае передаются три аргумента [`None`](https://python-all.ru/3.15/library/constants.html#None).280281   Если блок был завершён из-за исключения и возвращаемое значение метода [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) было ложным, исключение возбуждается повторно. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается с оператора, следующего за оператором [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with).282283   Если блок был завершён по любой причине, кроме исключения, возвращаемое значение [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) игнорируется, и выполнение продолжается в обычном месте для данного типа завершения.284285Следующий код:286287```python288with EXPRESSION as TARGET:289    SUITE290```291292семантически эквивалентен следующему:293294```python295manager = (EXPRESSION)296enter = manager.__enter__297exit = manager.__exit__298value = enter()299hit_except = False300301try:302    TARGET = value303    SUITE304except:305    hit_except = True306    if not exit(*sys.exc_info()):307        raise308finally:309    if not hit_except:310        exit(None, None, None)311```312313за исключением того, что для [`__enter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__enter__) и [`__exit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__exit__) используется неявный [поиск специальных методов](https://python-all.ru/3.15/reference/datamodel.html#special-lookup).314315При наличии нескольких элементов менеджеры контекста обрабатываются так, как если бы несколько операторов [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) были вложены:316317```python318with A() as a, B() as b:319    SUITE320```321322семантически эквивалентен следующему:323324```python325with A() as a:326    with B() as b:327        SUITE328```329330Можно также записывать многоэлементные менеджеры контекста в несколько строк, если элементы заключены в круглые скобки. Например:331332```python333with (334    A() as a,335    B() as b,336):337    SUITE338```339340Изменено в версии 3.1: Поддержка нескольких выражений контекста.341342Изменено в версии 3.10: Поддержка использования группирующих круглых скобок для разбиения инструкции на несколько строк.343344> **См. также**345>346> **[**PEP 343**](https://python-all.ru/3.15/reference/compound_stmts.html) – Оператор «with»**347>348> Спецификация, предыстория и примеры для инструкции [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with) в Python.349350## 8.6. Инструкция `match`351352Добавлено в версии 3.10.353354Оператор match используется для сопоставления с образцом. Синтаксис:355356```357358match_stmt:   'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT359subject_expr: flexible_expression "," [flexible_expression_list [',']]360              | assignment_expression361case_block:   'case' patterns [guard] ":" suite362```363364> **Примечание**365>366> В этом разделе для обозначения [мягких ключевых слов](https://python-all.ru/3.15/reference/lexical_analysis.html#soft-keywords) используются одинарные кавычки.367368Сопоставление с образцом принимает шаблон (после `case`) и значение-субъект (после `match`). Шаблон (который может содержать подшаблоны) сравнивается со значением-субъектом. Результаты:369370- Успех или неудача сопоставления (также называется успехом или неудачей шаблона).371- Возможное связывание сопоставленных значений с именем. Предварительные условия для этого обсуждаются далее.372373Ключевые слова `match` и `case` являются [мягкими ключевыми словами](https://python-all.ru/3.15/reference/lexical_analysis.html#soft-keywords).374375> **См. также**376>377> - [**PEP 634**](https://python-all.ru/3.15/reference/compound_stmts.html) – Структурное сопоставление с образцом: спецификация378> - [**PEP 636**](https://python-all.ru/3.15/reference/compound_stmts.html) – Структурное сопоставление с образцом: учебное пособие379380### 8.6.1. Обзор381382Вот обзор логического потока оператора match:3833841. Выражение-субъект `subject_expr` вычисляется, и получается результирующее значение-субъект. Если выражение-субъект содержит запятую, кортеж создаётся с использованием [стандартных правил](https://python-all.ru/3.15/library/stdtypes.html#typesseq-tuple).3852. Каждый шаблон в `case_block` пытается совпасть со значением-субъектом. Конкретные правила успеха или неудачи описаны ниже. Попытка сопоставления также может связывать некоторые или все отдельные имена внутри шаблона. Точные правила связывания имён различаются в зависимости от типа шаблона и указаны ниже. **Связывания имён, выполненные во время успешного сопоставления с образцом, переживают выполненный блок и могут использоваться после оператора match**.386387   > **Примечание**388   >389   > При неудачных сопоставлениях некоторые подшаблоны могут оказаться успешными. Не полагайтесь на то, что связывания выполняются для неудачного сопоставления. И наоборот, не полагайтесь на то, что переменные остаются неизменными после неудачного сопоставления. Точное поведение зависит от реализации и может различаться. Это намеренное решение, позволяющее различным реализациям добавлять оптимизации.3903. Если шаблон успешен, вычисляется соответствующее условие (guard), если оно присутствует. В этом случае все связывания имён гарантированно выполнены.391392   - Если условие вычисляется как истина или отсутствует, выполняется `block` внутри `case_block`.393   - В противном случае выполняется попытка следующего `case_block`, как описано выше.394   - Если больше нет блоков case, оператор match завершается.395396> **Примечание**397>398> Пользователям обычно не следует полагаться на то, что шаблон будет вычислен. В зависимости от реализации интерпретатор может кэшировать значения или использовать другие оптимизации, которые пропускают повторные вычисления.399400Пример оператора match:401402```python403>>> flag = False404>>> match (100, 200):405...    case (100, 300):  # Несоответствие: 200 != 300406...        print('Case 1')407...    case (100, 200) if flag:  # Успешное сопоставление, но страж не сработал408...        print('Case 2')409...    case (100, y):  # Сопоставляется и связывает y с 200410...        print(f'Case 3, y: {y}')411...    case _:  # Шаблон не был задействован412...        print('Case 4, I match anything!')413...414Case 3, y: 200415```416417В данном случае `if flag` – это страж. Подробнее об этом в следующем разделе.418419### 8.6.2. Стражи420421```422423guard: "if" assignment_expression424```425426`guard` (являющийся частью `case`) должен успешно выполниться, чтобы код внутри блока `case` был выполнен. Он принимает форму: [`if`](https://python-all.ru/3.15/reference/compound_stmts.html#if) за которым следует выражение.427428Логический ход выполнения блока `case` с `guard` следующий:4294301. Проверка, успешно ли сопоставился шаблон в блоке `case`. Если шаблон не совпал, `guard` не вычисляется и проверяется следующий блок `case`.4312. Если шаблон совпал, вычисляется `guard`.432433   - Если условие `guard` принимает значение true, выбирается блок case.434   - Если условие `guard` принимает значение false, блок case не выбирается.435   - Если при вычислении `guard` возникает исключение, оно всплывает.436437Стражам разрешено иметь побочные эффекты, поскольку они являются выражениями. Вычисление стражей должно выполняться последовательно от первого блока case к последнему, пропуская блоки case, шаблоны которых не совпали все. (Т.е. вычисление стражей должно происходить по порядку.) Вычисление стражей должно останавливаться, как только выбран блок case.438439### 8.6.3. Неопровержимые блоки case440441Неопровержимый блок case – это блок, который совпадает всегда. Оператор match может иметь не более одного неопровержимого блока case, и он должен быть последним.442443Блок case считается неопровержимым, если у него нет стража, а его шаблон неопровержим. Шаблон считается неопровержимым, если из одного только его синтаксиса можно доказать, что он всегда будет успешным. К неопровержимым относятся только следующие шаблоны:444445- [AS-шаблоны](https://python-all.ru/3.15/reference/compound_stmts.html#as-patterns), левая часть которых неопровержима446- [OR-шаблоны](https://python-all.ru/3.15/reference/compound_stmts.html#or-patterns), содержащие хотя бы один неопровержимый шаблон447- [Связывающие шаблоны](https://python-all.ru/3.15/reference/compound_stmts.html#capture-patterns)448- [Шаблоны-заглушки](https://python-all.ru/3.15/reference/compound_stmts.html#wildcard-patterns)449- неопровержимые шаблоны в скобках450451### 8.6.4. Шаблоны452453> **Примечание**454>455> В этом разделе используются обозначения грамматики, выходящие за рамки стандартного EBNF:456>457> - обозначение `SEP.RULE+` является сокращением для `RULE (SEP RULE)*`458> - обозначение `!RULE` является сокращением для негативного опережающего утверждения459460Синтаксис верхнего уровня для `patterns`:461462```463464patterns:       open_sequence_pattern | pattern465pattern:        as_pattern | or_pattern466closed_pattern: | literal_pattern467                | capture_pattern468                | wildcard_pattern469                | value_pattern470                | group_pattern471                | sequence_pattern472                | mapping_pattern473                | class_pattern474```475476Приведённые ниже описания будут включать описание «простым языком» того, что делает шаблон, в иллюстративных целях (благодарность Раймонду Хеттингеру за документ, вдохновивший большинство описаний). Обратите внимание, что эти описания предназначены исключительно для иллюстрации и **могут не** отражать реальную реализацию. Более того, они не охватывают все допустимые формы.477478#### 8.6.4.1. OR-шаблоны479480OR-шаблон – это два или более шаблона, разделённых вертикальной чертой `|`. Синтаксис:481482```483484or_pattern: "|".closed_pattern+485```486487Только последний подшаблон может быть [неопровержимым](https://python-all.ru/3.15/reference/compound_stmts.html#irrefutable-case), и каждый подшаблон должен связывать один и тот же набор имён, чтобы избежать неоднозначности.488489OR-шаблон по очереди сопоставляет каждый из своих подшаблонов с проверяемым значением, пока один из них не совпадёт. Тогда OR-шаблон считается успешным. В противном случае, если ни один из подшаблонов не совпал, OR-шаблон терпит неудачу.490491Простыми словами, `P1 | P2 | ...` попытается сопоставить `P1`; если это не удастся, он попробует сопоставить `P2`, успешно завершаясь при первом же совпадении, иначе завершаясь неудачей.492493#### 8.6.4.2. AS-шаблоны494495AS-шаблон сопоставляет OR-шаблон слева от ключевого слова [`as`](https://python-all.ru/3.15/reference/compound_stmts.html#as) с проверяемым значением. Синтаксис:496497```498499as_pattern: or_pattern "as" capture_pattern500```501502Если OR-шаблон терпит неудачу, AS-шаблон также терпит неудачу. В противном случае AS-шаблон связывает проверяемое значение с именем справа от ключевого слова as и завершается успешно. `capture_pattern` не может быть `_`.503504Простыми словами, `P as NAME` совпадает с `P`, и в случае успеха устанавливает `NAME = <subject>`.505506#### 8.6.4.3. Литеральные шаблоны507508Литеральный шаблон соответствует большинству [литералов](https://python-all.ru/3.15/reference/lexical_analysis.html#literals) в Python. Синтаксис:509510```511512literal_pattern: signed_number513                 | signed_number "+" NUMBER514                 | signed_number "-" NUMBER515                 | strings516                 | "None"517                 | "True"518                 | "False"519signed_number:   ["+" | "-"] NUMBER520```521522Правило `strings` и токен `NUMBER` определены в [стандартной грамматике Python](https://python-all.ru/3.15/reference/grammar.html). Поддерживаются строки в тройных кавычках. Поддерживаются сырые строки и строки байтов. [f-строки](https://python-all.ru/3.15/reference/lexical_analysis.html#f-strings) и [t-строки](https://python-all.ru/3.15/reference/lexical_analysis.html#t-strings) не поддерживаются.523524Формы `signed_number '+' NUMBER` и `signed_number '-' NUMBER` предназначены для представления [комплексных чисел](https://python-all.ru/3.15/reference/lexical_analysis.html#imaginary); они требуют действительное число слева и мнимое число справа. Например, `3 + 4j`.525526Простыми словами, `LITERAL` будет успешным только если `<subject> == LITERAL`. Для синглтонов `None`, `True` и `False` используется оператор [`is`](https://python-all.ru/3.15/reference/expressions.html#is).527528#### 8.6.4.4. Захватывающие шаблоны529530Захватывающий шаблон связывает проверяемое значение с именем. Синтаксис:531532```533534capture_pattern: !'_' NAME535```536537Одиночное подчеркивание `_` не является захватывающим шаблоном (именно это `!'_'` и выражает). Вместо этого оно обрабатывается как [`wildcard_pattern`](https://python-all.ru/3.15/reference/compound_stmts.html#grammar-token-python-grammar-wildcard_pattern).538539В данном шаблоне конкретное имя может быть связано только один раз. Например, `case x, x: ...` недопустимо, в то время как `case [x] | x: ...` разрешено.540541Захватывающие шаблоны всегда успешны. Связывание следует правилам области видимости, установленным оператором выражений присваивания в [**PEP 572**](https://python-all.ru/3.15/reference/compound_stmts.html); имя становится локальной переменной в ближайшей содержащей функции, если только нет применимого оператора [`global`](https://python-all.ru/3.15/reference/simple_stmts.html#global) или [`nonlocal`](https://python-all.ru/3.15/reference/simple_stmts.html#nonlocal).542543Простыми словами, `NAME` всегда будет успешным и установит `NAME = <subject>`.544545#### 8.6.4.5. Подстановочные шаблоны546547Подстановочный шаблон всегда успешен (совпадает с чем угодно) и не связывает имя. Синтаксис:548549```550551wildcard_pattern: '_'552```553554`_` является [мягким ключевым словом](https://python-all.ru/3.15/reference/lexical_analysis.html#soft-keywords) в любом шаблоне, но только внутри шаблонов. Как обычно, это идентификатор, даже внутри `match` проверяемых выражений, `guard` и блоков `case`.555556Простыми словами, `_` всегда будет успешным.557558#### 8.6.4.6. Шаблоны значений559560Шаблон значения представляет именованное значение в Python. Синтаксис:561562```563564value_pattern: attr565attr:          name_or_attr "." NAME566name_or_attr:  attr | NAME567```568569Точечное имя в шаблоне разрешается с использованием стандартных [правил разрешения имён Python](https://python-all.ru/3.15/reference/executionmodel.html#resolve-names). Шаблон успешен, если найденное значение равно проверяемому значению (с использованием оператора равенства `==`).570571Простыми словами, `NAME1.NAME2` будет успешным только если `<subject> == NAME1.NAME2`572573> **Примечание**574>575> Если одно и то же значение встречается несколько раз в одном и том же операторе match, интерпретатор может кэшировать первое найденное значение и повторно использовать его вместо повторения того же поиска. Этот кэш строго привязан к конкретному выполнению данного оператора match.576577#### 8.6.4.7. Групповые шаблоны578579Групповой шаблон позволяет добавлять круглые скобки вокруг шаблонов, чтобы подчеркнуть предполагаемую группировку. В остальном он не имеет дополнительного синтаксиса. Синтаксис:580581```582583group_pattern: "(" pattern ")"584```585586Простыми словами, `(P)` имеет тот же эффект, что и `P`.587588#### 8.6.4.8. Шаблоны последовательностей589590Шаблон последовательности содержит несколько подшаблонов для сопоставления с элементами последовательности. Синтаксис похож на распаковку списка или кортежа.591592```593594sequence_pattern:       "[" [maybe_sequence_pattern] "]"595                        | "(" [open_sequence_pattern] ")"596open_sequence_pattern:  maybe_star_pattern "," [maybe_sequence_pattern]597maybe_sequence_pattern: ",".maybe_star_pattern+ ","?598maybe_star_pattern:     star_pattern | pattern599star_pattern:           "*" (capture_pattern | wildcard_pattern)600```601602Нет разницы, используются ли круглые скобки или квадратные скобки для шаблонов последовательностей (т.е. `(...)` vs `[...]`).603604> **Примечание**605>606> Одиночный шаблон, заключенный в круглые скобки без завершающей запятой (например, `(3 | 4)`), является [групповым шаблоном](https://python-all.ru/3.15/reference/compound_stmts.html#group-patterns). В то время как одиночный шаблон в квадратных скобках (например, `[3 | 4]`) по-прежнему является шаблоном последовательности.607608В шаблоне последовательности может быть не более одного звездного подшаблона. Звездный подшаблон может находиться в любой позиции. Если звездный подшаблон отсутствует, шаблон последовательности является шаблоном фиксированной длины; в противном случае это шаблон переменной длины.609610Ниже описан логический поток сопоставления шаблона последовательности с проверяемым значением:6116121. Если проверяемое значение не является последовательностью [\[2\]](https://python-all.ru/3.15/reference/compound_stmts.html#id23), шаблон последовательности не срабатывает.6132. Если проверяемое значение является экземпляром `str`, `bytes` или `bytearray`, шаблон последовательности не срабатывает.6143. Последующие шаги зависят от того, имеет ли шаблон последовательности фиксированную или переменную длину.615616   Если шаблон последовательности имеет фиксированную длину:617618   1. Если длина проверяемой последовательности не равна количеству подшаблонов, шаблон последовательности не совпадает.619   2. Подшаблоны в шаблоне последовательности сопоставляются слева направо с соответствующими элементами проверяемой последовательности. Сопоставление прекращается, как только один из подшаблонов не совпадает. Если все подшаблоны успешно совпали со своими элементами, шаблон последовательности считается совпавшим.620621   В противном случае, если шаблон последовательности имеет переменную длину:622623   1. Если длина проверяемой последовательности меньше количества незвёздных подшаблонов, шаблон последовательности не совпадает.624   2. Начальные незвёздные подшаблоны сопоставляются с соответствующими элементами так же, как для последовательностей фиксированной длины.625   3. Если предыдущий шаг выполнен успешно, звёздный подшаблон сопоставляется со списком, сформированным из оставшихся элементов проверяемой последовательности, за исключением элементов, соответствующих незвёздным подшаблонам, которые следуют за звёздным.626   4. Оставшиеся незвёздные подшаблоны сопоставляются с соответствующими элементами проверяемой последовательности так же, как для последовательности фиксированной длины.627628   > **Примечание**629   >630   > Длина проверяемой последовательности получается с помощью [`len()`](https://python-all.ru/3.15/library/functions.html#len) (то есть через протокол [`__len__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__len__)). Эта длина может кэшироваться интерпретатором аналогично [шаблонам значений](https://python-all.ru/3.15/reference/compound_stmts.html#value-patterns).631632Проще говоря, `[P1, P2, P3,``, P<N>]` совпадает только в том случае, если выполняются все следующие условия:633634- проверить, что `<subject>` является последовательностью635- `len(subject) == <N>`636- `P1` совпадает с `<subject>[0]` (обратите внимание, что это сопоставление может также связывать имена)637- `P2` совпадает с `<subject>[1]` (обратите внимание, что это сопоставление может также связывать имена)638- … и так далее для соответствующих пар шаблон/элемент.639640#### 8.6.4.9. Шаблоны отображений641642Шаблон отображения содержит один или несколько шаблонов пар ключ-значение. Синтаксис аналогичен созданию словаря. Синтаксис:643644```645646mapping_pattern:     "{" [items_pattern] "}"647items_pattern:       ",".key_value_pattern+ ","?648key_value_pattern:   (literal_pattern | value_pattern) ":" pattern649                     | double_star_pattern650double_star_pattern: "**" capture_pattern651```652653В шаблоне отображения может быть не более одного шаблона с двойной звёздочкой. Шаблон с двойной звёздочкой должен быть последним подшаблоном в шаблоне отображения.654655Повторяющиеся ключи в шаблонах отображений запрещены. Повторяющиеся литеральные ключи приводят к возникновению [`SyntaxError`](https://python-all.ru/3.15/library/exceptions.html#SyntaxError). Два ключа, которые в остальном имеют одинаковое значение, вызовут [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError) во время выполнения.656657Ниже описана логика сопоставления шаблона отображения со значением subject:6586591. Если значение subject не является отображением [\[3\]](https://python-all.ru/3.15/reference/compound_stmts.html#id24), шаблон отображения не совпадает.6602. Если каждый ключ, указанный в шаблоне отображения, присутствует в отображении subject, и шаблон для каждого ключа совпадает с соответствующим элементом отображения subject, то шаблон отображения считается совпавшим.6613. Если в шаблоне отображения обнаружены повторяющиеся ключи, шаблон считается недействительным. Для повторяющихся литеральных значений возбуждается [`SyntaxError`](https://python-all.ru/3.15/library/exceptions.html#SyntaxError); для именованных ключей с одинаковым значением – [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError).662663> **Примечание**664>665> Пары ключ-значение сопоставляются с помощью двухаргументной формы метода `get()` отображения subject. Совпавшие пары ключ-значение уже должны присутствовать в отображении, а не создаваться на лету через [`__missing__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__missing__) или [`__getitem__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__getitem__).666667Проще говоря, `{KEY1: P1, KEY2: P2, ... }` совпадает только при выполнении всех следующих условий:668669- проверить, что `<subject>` является отображением670- `KEY1 in <subject>`671- `P1` соответствует `<subject>[KEY1]`672- … и так далее для соответствующих пар КЛЮЧ/шаблон.673674#### 8.6.4.10. Шаблоны классов675676Шаблон класса представляет класс и его позиционные и именованные аргументы (если есть). Синтаксис:677678```679680class_pattern:       name_or_attr "(" [pattern_arguments ","?] ")"681pattern_arguments:   positional_patterns ["," keyword_patterns]682                     | keyword_patterns683positional_patterns: ",".pattern+684keyword_patterns:    ",".keyword_pattern+685keyword_pattern:     NAME "=" pattern686```687688Одно и то же имя ключа не должно повторяться в шаблонах классов.689690Ниже описана логика сопоставления шаблона класса со значением subject:6916921. Если `name_or_attr` не является экземпляром встроенного типа [`type`](https://python-all.ru/3.15/library/functions.html#type), возбуждается [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError).6932. Если проверяемое значение не является экземпляром `name_or_attr` (проверка выполняется с помощью [`isinstance()`](https://python-all.ru/3.15/library/functions.html#isinstance)), то шаблон класса не срабатывает.6943. Если аргументы шаблона отсутствуют, шаблон считается успешным. В противном случае последующие шаги зависят от того, присутствуют ли именованные или позиционные аргументы шаблона.695696   Для ряда встроенных типов (перечисленных ниже) допускается один позиционный подшаблон, который сопоставляется со всем проверяемым значением; для этих типов именованные шаблоны также работают, как и для других типов.697698   Если присутствуют только именованные шаблоны, они обрабатываются следующим образом, по одному:699700   1. Имя (ключ) ищется как атрибут проверяемого значения.701702      - Если при этом возникает исключение, отличное от [`AttributeError`](https://python-all.ru/3.15/library/exceptions.html#AttributeError), исключение всплывает.703      - Если при этом возникает [`AttributeError`](https://python-all.ru/3.15/library/exceptions.html#AttributeError), шаблон класса считается несостоявшимся.704      - В противном случае подшаблон, связанный с именованным шаблоном, сопоставляется со значением атрибута проверяемого значения. Если сопоставление не удаётся, шаблон класса не срабатывает; если успешно, проверка переходит к следующему именованному аргументу.705   2. Если все именованные шаблоны успешны, шаблон класса считается успешным.706707   Если присутствуют позиционные шаблоны, они преобразуются в именованные шаблоны с помощью атрибута [`__match_args__`](https://python-all.ru/3.15/reference/datamodel.html#object.__match_args__) класса `name_or_attr` перед сопоставлением:708709   1. Вызывается эквивалент `getattr(cls, "__match_args__", ())`.710711      - Если при этом возникает исключение, оно всплывает.712      - Если возвращённое значение не является кортежем, преобразование не удаётся, и возбуждается [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError).713      - Если количество позиционных шаблонов превышает `len(cls.__match_args__)`, возбуждается [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError).714      - В противном случае позиционный шаблон `i` преобразуется в именованный шаблон с использованием `__match_args__[i]` в качестве ключа. `__match_args__[i]` должен быть строкой; в противном случае возбуждается [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError).715      - При наличии повторяющихся ключей возбуждается [`TypeError`](https://python-all.ru/3.15/library/exceptions.html#TypeError).716717      > **См. также**718      >719      > [Настройка позиционных аргументов в сопоставлении с шаблоном класса](https://python-all.ru/3.15/reference/datamodel.html#class-pattern-matching)720   2. После преобразования всех позиционных шаблонов в именованные сопоставление продолжается так, как если бы присутствовали только именованные шаблоны.721722   Для следующих встроенных типов обработка позиционных подшаблонов отличается:723724   - [`bool`](https://python-all.ru/3.15/library/functions.html#bool)725   - [`bytearray`](https://python-all.ru/3.15/library/stdtypes.html#bytearray)726   - [`bytes`](https://python-all.ru/3.15/library/stdtypes.html#bytes)727   - [`dict`](https://python-all.ru/3.15/library/stdtypes.html#dict)728   - [`float`](https://python-all.ru/3.15/library/functions.html#float)729   - [`frozendict`](https://python-all.ru/3.15/library/stdtypes.html#frozendict)730   - [`frozenset`](https://python-all.ru/3.15/library/stdtypes.html#frozenset)731   - [`int`](https://python-all.ru/3.15/library/functions.html#int)732   - [`list`](https://python-all.ru/3.15/library/stdtypes.html#list)733   - [`set`](https://python-all.ru/3.15/library/stdtypes.html#set)734   - [`str`](https://python-all.ru/3.15/library/stdtypes.html#str)735   - [`tuple`](https://python-all.ru/3.15/library/stdtypes.html#tuple)736737   Эти классы принимают один позиционный аргумент, и шаблон в этом случае сопоставляется со всем объектом, а не с атрибутом. Например, `int(0|1)` соответствует значению `0`, но не значению `0.0`.738739Проще говоря, `CLS(P1, attr=P2)` соответствует только в том случае, если происходит следующее:740741- `isinstance(<subject>, CLS)`742- преобразовать `P1` в именованный шаблон с помощью `CLS.__match_args__`743- Для каждого именованного аргумента `attr=P2`:744745  - `hasattr(<subject>, "attr")`746  - `P2` соответствует `<subject>.attr`747- … и так далее для соответствующей пары именованный аргумент/шаблон.748749> **См. также**750>751> - [**PEP 634**](https://python-all.ru/3.15/reference/compound_stmts.html) – Структурное сопоставление с образцом: спецификация752> - [**PEP 636**](https://python-all.ru/3.15/reference/compound_stmts.html) – Структурное сопоставление с образцом: учебное пособие753754## 8.7. Определения функций755756Определение функции создаёт объект пользовательской функции (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.15/reference/datamodel.html#types)):757758```759760funcdef:                   [decorators] "def" funcname [type_params] "(" [parameter_list] ")"761                           ["->" expression] ":" suite762decorators:                decorator+763decorator:                 "@" assignment_expression NEWLINE764parameter_list:            defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]765                             | parameter_list_no_posonly766parameter_list_no_posonly: defparameter ("," defparameter)* ["," [parameter_list_starargs]]767                           | parameter_list_starargs768parameter_list_starargs:   "*" [star_parameter] ("," defparameter)* ["," [parameter_star_kwargs]]769                           | "*" ("," defparameter)+ ["," [parameter_star_kwargs]]770                           | parameter_star_kwargs771parameter_star_kwargs:     "**" parameter [","]772parameter:                 identifier [":" expression]773star_parameter:            identifier [":" ["*"] expression]774defparameter:              parameter ["=" expression]775funcname:                  identifier776```777778Определение функции – это исполняемый оператор. Его выполнение связывает имя функции в текущей локальной области видимости с объектом функции (обёрткой над исполняемым кодом функции). Этот объект функции содержит ссылку на текущую глобальную область видимости, которая будет использоваться при вызове функции.779780Определение функции не выполняет тело функции; оно выполняется только при вызове функции. [\[4\]](https://python-all.ru/3.15/reference/compound_stmts.html#id25)781782Определение функции может быть обёрнуто одним или несколькими выражениями [декоратора](https://python-all.ru/3.15/glossary.html#term-decorator). Выражения декоратора вычисляются при определении функции в области видимости, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращённое значение связывается с именем функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код783784```python785@f1(arg)786@f2787def func(): pass788```789790примерно эквивалентно791792```python793def func(): pass794func = f1(arg)(f2(func))795```796797за исключением того, что исходная функция не привязывается временно к имени `func`.798799Изменено в версии 3.9: Функции могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.15/reference/expressions.html#grammar-token-python-grammar-assignment_expression). Ранее грамматика была гораздо более строгой; подробнее см. [**PEP 614**](https://python-all.ru/3.15/reference/compound_stmts.html).800801Список [параметров типа](https://python-all.ru/3.15/reference/compound_stmts.html#type-params) может быть указан в квадратных скобках между именем функции и открывающей скобкой её списка параметров. Это указывает статическим проверяльщикам типов, что функция является обобщённой. Во время выполнения параметры типа можно получить из атрибута [`__type_params__`](https://python-all.ru/3.15/reference/datamodel.html#function.__type_params__) функции. Подробнее см. [Generic functions](https://python-all.ru/3.15/reference/compound_stmts.html#generic-functions).802803Изменено в версии 3.12: Списки параметров типа появились в Python 3.12.804805Когда один или несколько [параметров](https://python-all.ru/3.15/glossary.html#term-parameter) имеют вид *параметр* `=` *выражение*, говорят, что функция имеет «значения параметров по умолчанию». Для параметра со значением по умолчанию соответствующий [аргумент](https://python-all.ru/3.15/glossary.html#term-argument) может быть опущен при вызове, и в этом случае подставляется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры до «`*`» также должны иметь значение по умолчанию – это синтаксическое ограничение, которое не отражено в грамматике.806807**Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции.** Это означает, что выражение вычисляется один раз, когда функция определяется, и одно и то же «вычисленное заранее» значение используется при каждом вызове. Это особенно важно понимать, когда значением параметра по умолчанию является изменяемый объект, например список или словарь: если функция изменяет объект (например, добавляя элемент в список), то значение по умолчанию фактически изменяется. Обычно это не то, что предполагалось. Один из способов обойти это – использовать `None` в качестве значения по умолчанию и явно проверять его в теле функции, например:808809```python810def whats_on_the_telly(penguin=None):811    if penguin is None:812        penguin = []813    penguin.append("property of the zoo")814    return penguin815```816817Семантика вызова функций подробно описана в разделе [Calls](https://python-all.ru/3.15/reference/expressions.html#calls). Вызов функции всегда присваивает значения всем параметрам, указанным в списке параметров, либо из позиционных аргументов, либо из именованных аргументов, либо из значений по умолчанию. Если присутствует форма «`*identifier`», она инициализируется кортежем, принимающим все лишние позиционные параметры, по умолчанию пустой кортеж. Если присутствует форма «`**identifier`», она инициализируется новым упорядоченным отображением, принимающим все лишние именованные аргументы, по умолчанию новым пустым отображением того же типа. Параметры после «`*`» или «`*identifier`» являются параметрами только для ключевых слов и могут передаваться только именованными аргументами. Параметры до «`/`» являются параметрами только для позиции и могут передаваться только позиционными аргументами.818819Изменено в версии 3.8: Синтаксис параметра функции `/` может использоваться для обозначения позиционных параметров. Подробнее см. [**PEP 570**](https://python-all.ru/3.15/reference/compound_stmts.html).820821Параметры могут иметь [аннотацию](https://python-all.ru/3.15/glossary.html#term-function-annotation) вида «`: expression`» после имени параметра. Любой параметр может иметь аннотацию, даже параметры вида `*identifier` или `**identifier`. (Как частный случай, параметры вида `*identifier` могут иметь аннотацию «`: *expression`».) Функции могут иметь аннотацию «return» вида «`-> expression`» после списка параметров. Эти аннотации могут быть любым допустимым выражением Python. Наличие аннотаций не меняет семантику функции. См. [Annotations](https://python-all.ru/3.15/reference/compound_stmts.html#annotations) для получения дополнительной информации об аннотациях.822823Изменено в версии 3.11: Параметры вида «`*identifier`» могут иметь аннотацию «`: *expression`». См. [**PEP 646**](https://python-all.ru/3.15/reference/compound_stmts.html).824825Также можно создавать анонимные функции (функции, не привязанные к имени) для немедленного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе [Lambdas](https://python-all.ru/3.15/reference/expressions.html#lambda). Обратите внимание, что лямбда-выражение – это всего лишь сокращение для упрощённого определения функции; функцию, определённую в инструкции «[`def`](https://python-all.ru/3.15/reference/compound_stmts.html#def)», можно передавать или присваивать другому имени так же, как функцию, определённую лямбда-выражением. Форма «`def`» на самом деле более мощная, поскольку позволяет выполнять несколько инструкций и аннотаций.826827**Замечание программисту:** Функции – объекты первого класса. Инструкция «`def`», выполненная внутри определения функции, определяет локальную функцию, которую можно вернуть или передать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробнее см. раздел [Naming and binding](https://python-all.ru/3.15/reference/executionmodel.html#naming).828829> **См. также**830>831> **[**PEP 3107**](https://python-all.ru/3.15/reference/compound_stmts.html) – Аннотации функций**832>833> Оригинальная спецификация аннотаций функций.834>835> **[**PEP 484**](https://python-all.ru/3.15/reference/compound_stmts.html) – Аннотации типов**836>837> Определение стандартного значения аннотаций: подсказки типов.838>839> **[**PEP 526**](https://python-all.ru/3.15/reference/compound_stmts.html) - Синтаксис аннотаций переменных**840>841> Возможность аннотировать типы объявлений переменных, включая переменные класса и переменные экземпляра.842>843> **[**PEP 563**](https://python-all.ru/3.15/reference/compound_stmts.html) – Отложенное вычисление аннотаций**844>845> Поддержка прямых ссылок в аннотациях путём сохранения аннотаций в строковом виде во время выполнения вместо немедленного вычисления.846>847> **[**PEP 318**](https://python-all.ru/3.15/reference/compound_stmts.html) – Декораторы для функций и методов**848>849> Были введены декораторы функций и методов. Декораторы классов были введены в [**PEP 3129**](https://python-all.ru/3.15/reference/compound_stmts.html).850851## 8.8. Определения классов852853Определение класса создаёт объект класса (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.15/reference/datamodel.html#types)):854855```856857classdef:    [decorators] "class" classname [type_params] [inheritance] ":" suite858inheritance: "(" [argument_list] ")"859classname:   identifier860```861862Определение класса – это исполняемая инструкция. Список наследования обычно содержит список базовых классов (см. [Метаклассы](https://python-all.ru/3.15/reference/datamodel.html#metaclasses) для более продвинутого использования), поэтому каждый элемент списка должен вычисляться в объект класса, который допускает создание подклассов. Классы без списка наследования по умолчанию наследуют от базового класса [`object`](https://python-all.ru/3.15/library/functions.html#object); следовательно,863864```python865class Foo:866    pass867```868869эквивалентна870871```python872class Foo(object):873    pass874```875876Базовых классов может быть один или несколько; подробнее см. [Множественное наследование](https://python-all.ru/3.15/reference/compound_stmts.html#multiple-inheritance) ниже.877878Затем тело класса выполняется в новом фрейме выполнения (см. [Naming and binding](https://python-all.ru/3.15/reference/executionmodel.html#naming)), используя только что созданное локальное пространство имён и исходное глобальное пространство имён. (Обычно тело содержит в основном определения функций.) Когда выполнение тела класса завершается, его фрейм выполнения отбрасывается, но локальное пространство имён сохраняется. [\[5\]](https://python-all.ru/3.15/reference/compound_stmts.html#id26) Затем создаётся объект класса с использованием списка наследования для базовых классов и сохранённого локального пространства имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.879880Порядок, в котором атрибуты определяются в теле класса, сохраняется в [`__dict__`](https://python-all.ru/3.15/reference/datamodel.html#type.__dict__) нового класса. Обратите внимание, что это надёжно только сразу после создания класса и только для классов, определённых с использованием синтаксиса определения.881882Создание класса можно сильно настраивать с помощью [метаклассов](https://python-all.ru/3.15/reference/datamodel.html#metaclasses).883884Классы также могут быть декорированы: так же, как и при декорировании функций,885886```python887@f1(arg)888@f2889class Foo: pass890```891892примерно эквивалентно893894```python895class Foo: pass896Foo = f1(arg)(f2(Foo))897```898899Правила вычисления выражений декораторов такие же, как и для декораторов функций. Затем результат привязывается к имени класса.900901Изменено в версии 3.9: Классы могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.15/reference/expressions.html#grammar-token-python-grammar-assignment_expression). Ранее грамматика была гораздо более строгой; подробнее см. [**PEP 614**](https://python-all.ru/3.15/reference/compound_stmts.html).902903Список [параметров типа](https://python-all.ru/3.15/reference/compound_stmts.html#type-params) может быть указан в квадратных скобках сразу после имени класса. Это сообщает статическим проверяющим типов, что класс является обобщённым. Во время выполнения параметры типа можно получить из атрибута класса [`__type_params__`](https://python-all.ru/3.15/reference/datamodel.html#type.__type_params__). Подробнее см. [Обобщённые классы](https://python-all.ru/3.15/reference/compound_stmts.html#generic-classes).904905Изменено в версии 3.12: Списки параметров типа появились в Python 3.12.906907**Замечание для программиста:** Переменные, определённые в определении класса, являются атрибутами класса; они разделяются экземплярами. Атрибуты экземпляра можно задать в методе с помощью `self.name = value`. Как атрибуты класса, так и атрибуты экземпляра доступны через запись “`self.name`”, и при таком обращении атрибут экземпляра скрывает атрибут класса с тем же именем. Атрибуты класса могут использоваться как значения по умолчанию для атрибутов экземпляра, но использование изменяемых значений может привести к неожиданным результатам. [Дескрипторы](https://python-all.ru/3.15/reference/datamodel.html#descriptors) можно использовать для создания переменных экземпляра с другими деталями реализации.908909> **См. также**910>911> **[**PEP 3115**](https://python-all.ru/3.15/reference/compound_stmts.html) – Метаклассы в Python 3000**912>913> Предложение, изменившее объявление метаклассов на текущий синтаксис, и семантику того, как конструируются классы с метаклассами.914>915> **[**PEP 3129**](https://python-all.ru/3.15/reference/compound_stmts.html) - Декораторы классов**916>917> Предложение, добавившее декораторы классов. Декораторы функций и методов были введены в [**PEP 318**](https://python-all.ru/3.15/reference/compound_stmts.html).918919### 8.8.1. Множественное наследование920921Классы Python могут иметь несколько базовых классов – это называется *множественным наследованием*. Базовые классы указываются в определении класса в круглых скобках после имени класса через запятую. Например, следующее определение класса:922923```pycon924>>> class A: pass925>>> class B: pass926>>> class C(A, B): pass927```928929определяет класс `C`, который наследуется от классов `A` и `B`.930931[Порядок разрешения методов](https://python-all.ru/3.15/glossary.html#term-method-resolution-order) (MRO) – это порядок, в котором базовые классы просматриваются при поиске атрибута класса. Описание того, как Python определяет MRO для класса, см. в [The Python 2.3 Method Resolution Order](https://python-all.ru/3.15/howto/mro.html#python-2-3-mro).932933Множественное наследование разрешено не всегда. Попытка определить класс с множественным наследованием вызовет ошибку, если один из базовых классов не допускает создания подклассов, если не удаётся построить согласованный MRO, если не удаётся определить корректный метакласс или если возникает конфликт размещения экземпляров. Рассмотрим каждую из этих причин по порядку.934935Во-первых, все базовые классы должны допускать создание подклассов. Хотя большинство классов это позволяют, некоторые встроенные классы – нет, например [`bool`](https://python-all.ru/3.15/library/functions.html#bool):936937```pycon938>>> class SubBool(bool):  # TypeError939...    pass940Traceback (most recent call last):941   ...942TypeError: type 'bool' is not an acceptable base type943```944945В разрешённом MRO класса базовые классы располагаются в том порядке, в котором они указаны в списке базовых классов. Кроме того, MRO всегда перечисляет дочерний класс раньше любого из его базовых. Определение класса завершится ошибкой, если из предоставленного списка баз невозможно построить согласованный MRO, удовлетворяющий этим правилам:946947```pycon948>>> class Base: pass949>>> class Child(Base): pass950>>> class Grandchild(Base, Child): pass  # TypeError951Traceback (most recent call last):952   ...953TypeError: Cannot create a consistent method resolution order (MRO) for bases Base, Child954```955956В MRO класса `Grandchild` `Base` должен располагаться перед `Child`, поскольку он стоит первым в списке базовых классов, но при этом он должен располагаться после `Child`, так как является родителем `Child`. Это противоречие, поэтому класс не может быть определён.957958Если у некоторых базовых классов определён пользовательский [метакласс](https://python-all.ru/3.15/glossary.html#term-metaclass), то метакласс результирующего класса выбирается среди метаклассов базовых классов и явно указанного метакласса дочернего класса. Это должен быть метакласс, являющийся подклассом всех остальных кандидатов. Если среди кандидатов такого метакласса нет, класс не может быть создан, как описано в [Определение подходящего метакласса](https://python-all.ru/3.15/reference/datamodel.html#metaclass-determination).959960Наконец, макеты экземпляров базовых классов должны быть совместимы. Это означает, что для класса должна существовать возможность вычислить *неизменную базу*. Какие именно классы являются неизменными базами, зависит от реализации Python.961962**Особенность реализации CPython:** В CPython класс является неизменной базой, если он имеет непустое определение [`__slots__`](https://python-all.ru/3.15/reference/datamodel.html#object.__slots__). Многие, но не все классы, определённые на C, также являются неизменными базами, включая большинство встроенных (например, [`int`](https://python-all.ru/3.15/library/functions.html#int) или [`BaseException`](https://python-all.ru/3.15/library/exceptions.html#BaseException)), но исключая большинство конкретных классов [`Exception`](https://python-all.ru/3.15/library/exceptions.html#Exception). Как правило, класс на C является неизменной базой, если его внутренняя структура отличается по размеру от структуры его базового класса.963964У каждого класса есть неизменная база. [`object`](https://python-all.ru/3.15/library/functions.html#object), базовый класс, сам является своей неизменной базой. Если базовый класс один, то неизменная база дочернего класса – это этот класс, если он является неизменной базой; в противном случае – неизменная база базового класса. Если базовых классов несколько, сначала находится неизменная база для каждого базового класса, формируя список кандидатов в неизменные базы. Если среди них есть единственная неизменная база, являющаяся подклассом всех остальных, то она и становится неизменной базой. В противном случае создание класса завершается ошибкой.965966Пример:967968```pycon969>>> class Solid1:970...    __slots__ = ("solid1",)971>>>972>>> class Solid2:973...    __slots__ = ("solid2",)974>>>975>>> class SolidChild(Solid1):976...    __slots__ = ("solid_child",)977>>>978>>> class C1:  # фиксированный базовый класс – `object`979...    pass980>>>981>>> # OK: фиксированные базовые классы – `Solid1` и `object`, и `Solid1` является подклассом `object`.982>>> class C2(Solid1, C1):  # фиксированный базовый класс – `Solid1`983...    pass984>>>985>>> # OK: фиксированные базовые классы – `SolidChild` и `Solid1`, и `SolidChild` является подклассом `Solid1`.986>>> class C3(SolidChild, Solid1):  # фиксированный базовый класс – `SolidChild`987...    pass988>>>989>>> # Ошибка: фиксированные базовые классы – `Solid1` и `Solid2`, но ни один из них не является подклассом другого.990>>> class C4(Solid1, Solid2):  # ошибка: нет единственного фиксированного базового класса991...    pass992Traceback (most recent call last):993  ...994TypeError: multiple bases have instance lay-out conflict995```996997## 8.9. Корутины998999Добавлено в версии 3.5.10001001### 8.9.1. Определение корутинной функции10021003```10041005async_funcdef: [decorators] "async" "def" funcname "(" [parameter_list] ")"1006               ["->" expression] ":" suite1007```10081009Выполнение корутин Python может приостанавливаться и возобновляться во многих точках (см. [корутина](https://python-all.ru/3.15/glossary.html#term-coroutine)). Выражения [`await`](https://python-all.ru/3.15/reference/expressions.html#await), [`async for`](https://python-all.ru/3.15/reference/compound_stmts.html#async-for) и [`async with`](https://python-all.ru/3.15/reference/compound_stmts.html#async-with) можно использовать только в теле корутинной функции.10101011Функции, определённые с синтаксисом `async def`, всегда являются корутинными функциями, даже если они не содержат ключевых слов `await` или `async`.10121013Использование выражения `yield from` в теле корутинной функции является [`SyntaxError`](https://python-all.ru/3.15/library/exceptions.html#SyntaxError).10141015Пример корутинной функции:10161017```python1018async def func(param1, param2):1019    do_stuff()1020    await some_coroutine()1021```10221023Изменено в версии 3.7: `await` и `async` теперь являются ключевыми словами; ранее они рассматривались как таковые только внутри тела корутинной функции.10241025### 8.9.2. Инструкция `async for`10261027```10281029async_for_stmt: "async" for_stmt1030```10311032[Асинхронный итерируемый объект](https://python-all.ru/3.15/glossary.html#term-asynchronous-iterable) предоставляет метод `__aiter__`, который напрямую возвращает [асинхронный итератор](https://python-all.ru/3.15/glossary.html#term-asynchronous-iterator), способный вызывать асинхронный код в своём методе `__anext__`.10331034Инструкция `async for` обеспечивает удобную итерацию по асинхронным итерируемым объектам.10351036Следующий код:10371038```python1039async for TARGET in ITER:1040    SUITE1041else:1042    SUITE21043```10441045Семантически эквивалентен следующему:10461047```python1048iter = (ITER).__aiter__()1049running = True10501051while running:1052    try:1053        TARGET = await iter.__anext__()1054    except StopAsyncIteration:1055        running = False1056    else:1057        SUITE1058else:1059    SUITE21060```10611062за исключением того, что для [`__aiter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__aiter__) и [`__anext__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__anext__) используется неявный [поиск специальных методов](https://python-all.ru/3.15/reference/datamodel.html#special-lookup).10631064Использование инструкции `async for` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.15/library/exceptions.html#SyntaxError).10651066### 8.9.3. Инструкция `async with`10671068```10691070async_with_stmt: "async" with_stmt1071```10721073[Асинхронный менеджер контекста](https://python-all.ru/3.15/glossary.html#term-asynchronous-context-manager) – это [менеджер контекста](https://python-all.ru/3.15/glossary.html#term-context-manager), который может приостанавливать выполнение в своих методах *входа* и *выхода*.10741075Следующий код:10761077```python1078async with EXPRESSION as TARGET:1079    SUITE1080```10811082семантически эквивалентен следующему:10831084```python1085manager = (EXPRESSION)1086aenter = manager.__aenter__1087aexit = manager.__aexit__1088value = await aenter()1089hit_except = False10901091try:1092    TARGET = value1093    SUITE1094except:1095    hit_except = True1096    if not await aexit(*sys.exc_info()):1097        raise1098finally:1099    if not hit_except:1100        await aexit(None, None, None)1101```11021103за исключением того, что для [`__aenter__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__aenter__) и [`__aexit__()`](https://python-all.ru/3.15/reference/datamodel.html#object.__aexit__) используется неявный [поиск специальных методов](https://python-all.ru/3.15/reference/datamodel.html#special-lookup).11041105Использование инструкции `async with` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.15/library/exceptions.html#SyntaxError).11061107> **См. также**1108>1109> **[**PEP 492**](https://python-all.ru/3.15/reference/compound_stmts.html) - Корутины с синтаксисом async и await**1110>1111> Предложение, которое сделало корутины полноценной самостоятельной концепцией в Python и добавило поддерживающий синтаксис.11121113## 8.10. Списки параметров типа11141115Добавлено в версии 3.12.11161117Изменено в версии 3.13: Добавлена поддержка значений по умолчанию (см. [**PEP 696**](https://python-all.ru/3.15/reference/compound_stmts.html)).11181119```11201121type_params:  "[" type_param ("," type_param)* "]"1122type_param:   typevar | typevartuple | paramspec1123typevar:      identifier (":" expression)? ("=" expression)?1124typevartuple: "*" identifier ("=" expression)?1125paramspec:    "**" identifier ("=" expression)?1126```11271128[Функции](https://python-all.ru/3.15/reference/compound_stmts.html#def) (включая [корутины](https://python-all.ru/3.15/reference/compound_stmts.html#async-def)), [классы](https://python-all.ru/3.15/reference/compound_stmts.html#class) и [псевдонимы типов](https://python-all.ru/3.15/reference/simple_stmts.html#type) могут содержать список параметров типа:11291130```python1131def max[T](args: list[T]) -> T:1132    ...11331134async def amax[T](args: list[T]) -> T:1135    ...11361137class Bag[T]:1138    def __iter__(self) -> Iterator[T]:1139        ...11401141    def add(self, arg: T) -> None:1142        ...11431144type ListOrSet[T] = list[T] | set[T]1145```11461147Семантически это указывает, что функция, класс или псевдоним типа является обобщённым относительно переменной типа. Эта информация в первую очередь используется статическими проверяющими типов, а во время выполнения обобщённые объекты ведут себя почти так же, как их необобщённые аналоги.11481149Параметры типа объявляются в квадратных скобках (`[]`) сразу после имени функции, класса или псевдонима типа. Параметры типа доступны в области видимости обобщённого объекта, но не за её пределами. Так, после объявления `def func[T](): pass` имя `T` недоступно в области видимости модуля. Ниже семантика обобщённых объектов описывается более точно. Область видимости параметров типа моделируется с помощью специальной функции (технически – [области аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes)), которая оборачивает создание обобщённого объекта.11501151Обобщённые функции, классы и псевдонимы типов имеют атрибут [`__type_params__`](https://python-all.ru/3.15/library/stdtypes.html#definition.__type_params__), перечисляющий их параметры типа.11521153Параметры типа бывают трёх видов:11541155- [`typing.TypeVar`](https://python-all.ru/3.15/library/typing.html#typing.TypeVar) – вводится простым именем (например, `T`). Семантически это представляет единственный тип для проверщика типов.1156- [`typing.TypeVarTuple`](https://python-all.ru/3.15/library/typing.html#typing.TypeVarTuple) – вводится именем с префиксом из одной звёздочки (например, `*Ts`). Семантически обозначает кортеж из произвольного количества типов.1157- [`typing.ParamSpec`](https://python-all.ru/3.15/library/typing.html#typing.ParamSpec) – вводится именем с префиксом из двух звёздочек (например, `**P`). Семантически обозначает параметры вызываемого объекта.11581159Объявления [`typing.TypeVar`](https://python-all.ru/3.15/library/typing.html#typing.TypeVar) могут определять *границы* и *ограничения* с двоеточием (`:`), после которого идёт выражение. Одно выражение после двоеточия указывает границу (например, `T: int`). Семантически это означает, что `typing.TypeVar` может представлять только типы, являющиеся подтипом этой границы. Заключённый в скобки кортеж выражений после двоеточия указывает набор ограничений (например, `T: (str, bytes)`). Каждый элемент кортежа должен быть типом (опять же, это не проверяется во время выполнения). Переменная типа с ограничениями может только принимать один из типов из списка ограничений.11601161Для параметров `typing.TypeVar`, объявленных с помощью синтаксиса списка параметров типа, граница и ограничения не вычисляются при создании обобщённого объекта, а только при явном обращении к значению через атрибуты `__bound__` и `__constraints__`. Для этого границы или ограничения вычисляются в отдельной [области аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes).11621163[`typing.TypeVarTuple`](https://python-all.ru/3.15/library/typing.html#typing.TypeVarTuple) и [`typing.ParamSpec`](https://python-all.ru/3.15/library/typing.html#typing.ParamSpec) не могут иметь границ или ограничений.11641165Все три разновидности параметров типа также могут иметь *значение по умолчанию*, которое используется, когда параметр типа не указан явно. Оно добавляется путём добавления одного знака равенства (`=`) с последующим выражением. Как и границы с ограничениями переменных типа, значение по умолчанию не вычисляется при создании объекта, а только при обращении к атрибуту `__default__` параметра типа. Для этого значение по умолчанию вычисляется в отдельной [области аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes). Если для параметра типа не указано значение по умолчанию, атрибут `__default__` устанавливается в специальный sentinel-объект [`typing.NoDefault`](https://python-all.ru/3.15/library/typing.html#typing.NoDefault).11661167Следующий пример показывает полный набор допустимых объявлений параметров типа:11681169```python1170def overly_generic[1171   SimpleTypeVar,1172   TypeVarWithDefault = int,1173   TypeVarWithBound: int,1174   TypeVarWithConstraints: (str, bytes),1175   *SimpleTypeVarTuple = (int, float),1176   **SimpleParamSpec = (str, bytearray),1177](1178   a: SimpleTypeVar,1179   b: TypeVarWithDefault,1180   c: TypeVarWithBound,1181   d: Callable[SimpleParamSpec, TypeVarWithConstraints],1182   *e: SimpleTypeVarTuple,1183): ...1184```11851186### 8.10.1. Обобщённые функции11871188Обобщённые функции объявляются следующим образом:11891190```python1191def func[T](arg: T): ...1192```11931194Этот синтаксис эквивалентен:11951196```python1197annotation-def TYPE_PARAMS_OF_func():1198    T = typing.TypeVar("T")1199    def func(arg: T): ...1200    func.__type_params__ = (T,)1201    return func1202func = TYPE_PARAMS_OF_func()1203```12041205Здесь `annotation-def` обозначает [область аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes), которая на самом деле не привязана ни к какому имени во время выполнения. (Ещё одна вольность допущена в преобразовании: синтаксис не использует доступ к атрибуту модуля [`typing`](https://python-all.ru/3.15/library/typing.html#module-typing), а создаёт экземпляр [`typing.TypeVar`](https://python-all.ru/3.15/library/typing.html#typing.TypeVar) напрямую.)12061207Аннотации обобщённых функций вычисляются в области аннотаций, используемой для объявления параметров типа, а значения по умолчанию и декораторы функции – нет.12081209Следующий пример иллюстрирует правила области видимости для этих случаев, а также для дополнительных разновидностей параметров типа:12101211```python1212@decorator1213def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):1214    ...1215```12161217За исключением [ленивого вычисления](https://python-all.ru/3.15/reference/executionmodel.html#lazy-evaluation) границы [`TypeVar`](https://python-all.ru/3.15/library/typing.html#typing.TypeVar), это эквивалентно:12181219```python1220DEFAULT_OF_arg = some_default12211222annotation-def TYPE_PARAMS_OF_func():12231224    annotation-def BOUND_OF_T():1225        return int1226    # На самом деле, BOUND_OF_T() вычисляется только по требованию.1227    T = typing.TypeVar("T", bound=BOUND_OF_T())12281229    Ts = typing.TypeVarTuple("Ts")1230    P = typing.ParamSpec("P")12311232    def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):1233        ...12341235    func.__type_params__ = (T, Ts, P)1236    return func1237func = decorator(TYPE_PARAMS_OF_func())1238```12391240Имена с заглавной буквы, такие как `DEFAULT_OF_arg`, на самом деле не привязаны во время выполнения.12411242### 8.10.2. Обобщённые классы12431244Обобщённые классы объявляются следующим образом:12451246```python1247class Bag[T]: ...1248```12491250Этот синтаксис эквивалентен:12511252```python1253annotation-def TYPE_PARAMS_OF_Bag():1254    T = typing.TypeVar("T")1255    class Bag(typing.Generic[T]):1256        __type_params__ = (T,)1257        ...1258    return Bag1259Bag = TYPE_PARAMS_OF_Bag()1260```12611262И снова `annotation-def` (не настоящее ключевое слово) обозначает [область аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes), а имя `TYPE_PARAMS_OF_Bag` на самом деле не привязано во время выполнения.12631264Обобщённые классы неявно наследуются от [`typing.Generic`](https://python-all.ru/3.15/library/typing.html#typing.Generic). Базовые классы и именованные аргументы обобщённых классов вычисляются в области видимости типа для параметров типа, а декораторы вычисляются за пределами этой области. Это иллюстрируется следующим примером:12651266```python1267@decorator1268class Bag(Base[T], arg=T): ...1269```12701271Это эквивалентно:12721273```python1274annotation-def TYPE_PARAMS_OF_Bag():1275    T = typing.TypeVar("T")1276    class Bag(Base[T], typing.Generic[T], arg=T):1277        __type_params__ = (T,)1278        ...1279    return Bag1280Bag = decorator(TYPE_PARAMS_OF_Bag())1281```12821283### 8.10.3. Обобщённые псевдонимы типов12841285Оператор [`type`](https://python-all.ru/3.15/reference/simple_stmts.html#type) также можно использовать для создания обобщённого псевдонима типа:12861287```python1288type ListOrSet[T] = list[T] | set[T]1289```12901291За исключением [ленивого вычисления](https://python-all.ru/3.15/reference/executionmodel.html#lazy-evaluation) значения, это эквивалентно:12921293```python1294annotation-def TYPE_PARAMS_OF_ListOrSet():1295    T = typing.TypeVar("T")12961297    annotation-def VALUE_OF_ListOrSet():1298        return list[T] | set[T]1299    # На самом деле, значение вычисляется лениво.1300    return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))1301ListOrSet = TYPE_PARAMS_OF_ListOrSet()1302```13031304Здесь `annotation-def` (не настоящее ключевое слово) обозначает [область аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes). Имена с заглавной буквы, такие как `TYPE_PARAMS_OF_ListOrSet`, на самом деле не привязаны во время выполнения.13051306## 8.11. Аннотации13071308Изменено в версии 3.14: Аннотации теперь по умолчанию вычисляются лениво.13091310Переменные и параметры функций могут иметь [аннотации](https://python-all.ru/3.15/glossary.html#term-annotation), создаваемые добавлением двоеточия после имени с последующим выражением:13111312```python1313x: annotation = 11314def f(param: annotation): ...1315```13161317Функции также могут иметь аннотацию возврата после стрелки:13181319```python1320def f() -> annotation: ...1321```13221323Аннотации традиционно используются для [подсказок типов](https://python-all.ru/3.15/glossary.html#term-type-hint), однако это не навязывается языком, и в общем случае аннотации могут содержать произвольные выражения. Наличие аннотаций не меняет семантику выполнения кода, за исключением случаев, когда используется механизм, который анализирует и использует аннотации (например, [`dataclasses`](https://python-all.ru/3.15/library/dataclasses.html#module-dataclasses) или [`functools.singledispatch()`](https://python-all.ru/3.15/library/functools.html#functools.singledispatch)).13241325По умолчанию аннотации вычисляются лениво в [области аннотаций](https://python-all.ru/3.15/reference/executionmodel.html#annotation-scopes). Это значит, что они не вычисляются во время выполнения кода, содержащего аннотацию. Вместо этого интерпретатор сохраняет информацию, которая может быть использована для последующего вычисления аннотации по запросу. Модуль [`annotationlib`](https://python-all.ru/3.15/library/annotationlib.html#module-annotationlib) предоставляет инструменты для вычисления аннотаций.13261327Если присутствует [future-оператор](https://python-all.ru/3.15/reference/simple_stmts.html#future) `from __future__ import annotations`, то все аннотации вместо этого сохраняются как строки:13281329```python1330>>> from __future__ import annotations1331>>> def f(param: annotation): ...1332>>> f.__annotations__1333{'param': 'annotation'}1334```13351336Этот future-оператор будет объявлен устаревшим и удален в одной из будущих версий Python, но не раньше, чем Python 3.13 достигнет конца своего жизненного цикла (см. [**PEP 749**](https://python-all.ru/3.15/reference/compound_stmts.html)). Когда он используется, инструменты интроспекции, такие как [`annotationlib.get_annotations()`](https://python-all.ru/3.15/library/annotationlib.html#annotationlib.get_annotations) и [`typing.get_type_hints()`](https://python-all.ru/3.15/library/typing.html#typing.get_type_hints), с меньшей вероятностью смогут разрешить аннотации во время выполнения.13371338Сноски13391340\[[1](https://python-all.ru/3.15/reference/compound_stmts.html#id1)\]13411342Исключение распространяется по стеку вызовов, если только не встретится предложение [`finally`](https://python-all.ru/3.15/reference/compound_stmts.html#finally), которое в свою очередь возбуждает другое исключение. Это новое исключение приводит к потере старого.13431344\[[2](https://python-all.ru/3.15/reference/compound_stmts.html#id11)\]13451346В сопоставлении с образцом последовательность определяется как одно из следующего:13471348- класс, который наследует от [`collections.abc.Sequence`](https://python-all.ru/3.15/library/collections.abc.html#collections.abc.Sequence)1349- класс Python, который был зарегистрирован как [`collections.abc.Sequence`](https://python-all.ru/3.15/library/collections.abc.html#collections.abc.Sequence)1350- встроенный класс, у которого установлен бит [`Py_TPFLAGS_SEQUENCE`](https://python-all.ru/3.15/c-api/typeobj.html#c.Py_TPFLAGS_SEQUENCE) (в CPython)1351- класс, который наследует от любого из вышеперечисленных13521353Следующие классы стандартной библиотеки являются последовательностями:13541355- [`array.array`](https://python-all.ru/3.15/library/array.html#array.array)1356- [`collections.deque`](https://python-all.ru/3.15/library/collections.html#collections.deque)1357- [`list`](https://python-all.ru/3.15/library/stdtypes.html#list)1358- [`memoryview`](https://python-all.ru/3.15/library/stdtypes.html#memoryview)1359- [`range`](https://python-all.ru/3.15/library/stdtypes.html#range)1360- [`tuple`](https://python-all.ru/3.15/library/stdtypes.html#tuple)13611362> **Примечание**1363>1364> Проверяемые значения типов `str`, `bytes` и `bytearray` не соответствуют шаблонам последовательностей.13651366\[[3](https://python-all.ru/3.15/reference/compound_stmts.html#id13)\]13671368В сопоставлении с образцом отображение определяется как одно из следующего:13691370- класс, который наследует от [`collections.abc.Mapping`](https://python-all.ru/3.15/library/collections.abc.html#collections.abc.Mapping)1371- класс Python, который был зарегистрирован как [`collections.abc.Mapping`](https://python-all.ru/3.15/library/collections.abc.html#collections.abc.Mapping)1372- встроенный класс, у которого установлен бит [`Py_TPFLAGS_MAPPING`](https://python-all.ru/3.15/c-api/typeobj.html#c.Py_TPFLAGS_MAPPING) (в CPython)1373- класс, который наследует от любого из вышеперечисленных13741375Классы стандартной библиотеки [`dict`](https://python-all.ru/3.15/library/stdtypes.html#dict) и [`types.MappingProxyType`](https://python-all.ru/3.15/library/types.html#types.MappingProxyType) являются отображениями.13761377\[[4](https://python-all.ru/3.15/reference/compound_stmts.html#id15)\]13781379Строковый литерал, который является первым оператором в теле функции, преобразуется в атрибут [`__doc__`](https://python-all.ru/3.15/reference/datamodel.html#function.__doc__) функции и, таким образом, становится её [докстрингом](https://python-all.ru/3.15/glossary.html#term-docstring).13801381\[[5](https://python-all.ru/3.15/reference/compound_stmts.html#id16)\]13821383Строковый литерал, который является первым оператором в теле класса, преобразуется в элемент [`__doc__`](https://python-all.ru/3.15/reference/datamodel.html#type.__doc__) пространства имён и, таким образом, становится [докстрингом](https://python-all.ru/3.15/glossary.html#term-docstring) класса.1384