compound_stmts.md
1> **Источник:** https://python-all.ru/3.10/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.10/reference/compound_stmts.html#if), [`while`](https://python-all.ru/3.10/reference/compound_stmts.html#while) и [`for`](https://python-all.ru/3.10/reference/compound_stmts.html#for) реализуют традиционные конструкции управления потоком. [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) задаёт обработчики исключений и/или код очистки для группы инструкций, а инструкция [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) позволяет выполнять код инициализации и финализации вокруг блока кода. Определения функций и классов также синтаксически являются составными инструкциями.1213Составная инструкция состоит из одного или нескольких «предложений». Предложение состоит из заголовка и «набора инструкций». Заголовки предложений одной составной инструкции находятся на одном уровне отступа. Каждый заголовок предложения начинается с уникального ключевого слова и завершается двоеточием. Набор инструкций – это группа инструкций, управляемая предложением. Набор инструкций может состоять из одной или нескольких простых инструкций, разделённых точкой с запятой, на той же строке, что и заголовок, после его двоеточия, или из одной или нескольких инструкций с отступом на последующих строках. Только вторая форма набора инструкций может содержать вложенные составные инструкции; следующий пример недопустим, в основном потому, что было бы непонятно, к какому предложению [`if`](https://python-all.ru/3.10/reference/compound_stmts.html#if) будет относиться последующее предложение [`else`](https://python-all.ru/3.10/reference/compound_stmts.html#else):1415```python16if test1: if test2: print(x)17```1819Также обратите внимание, что точка с запятой связывает сильнее, чем двоеточие в этом контексте, так что в следующем примере выполняются либо все вызовы [`print()`](https://python-all.ru/3.10/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.10/reference/compound_stmts.html#else)» решается в Python требованием, чтобы вложенные инструкции [`if`](https://python-all.ru/3.10/reference/compound_stmts.html#if) имели отступ).4647Форматирование грамматических правил в следующих разделах помещает каждое предложение на отдельную строку для ясности.4849## 8.1. Инструкция `if`5051Инструкция [`if`](https://python-all.ru/3.10/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.10/reference/expressions.html#booleans) для определения истины и лжи); затем этот набор выполняется (и никакая другая часть инструкции [`if`](https://python-all.ru/3.10/reference/compound_stmts.html#if) не выполняется и не вычисляется). Если все выражения ложны, выполняется набор инструкций предложения [`else`](https://python-all.ru/3.10/reference/compound_stmts.html#else), если оно присутствует.6162## 8.2. Инструкция `while`6364Инструкция [`while`](https://python-all.ru/3.10/reference/compound_stmts.html#while) используется для повторного выполнения, пока выражение истинно:6566```6768while_stmt ::= "while" assignment_expression ":" suite69 ["else" ":" suite]70```7172Эта инструкция многократно проверяет выражение и, если оно истинно, выполняет первый набор инструкций; если выражение ложно (возможно, при первой проверке), то набор инструкций предложения `else`, если оно присутствует, выполняется, и цикл завершается.7374Инструкция [`break`](https://python-all.ru/3.10/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.10/reference/simple_stmts.html#continue), выполненная в первом наборе, пропускает оставшуюся часть набора и возвращается к проверке выражения.7576## 8.3. Инструкция `for`7778Инструкция [`for`](https://python-all.ru/3.10/reference/compound_stmts.html#for) используется для перебора элементов последовательности (например, строки, кортежа или списка) или другого итерируемого объекта:7980```8182for_stmt ::= "for" target_list "in" expression_list ":" suite83 ["else" ":" suite]84```8586Список выражений вычисляется один раз; он должен давать итерируемый объект. Итератор создаётся для результата `expression_list`. Затем блок инструкций выполняется один раз для каждого элемента, предоставленного итератором, в порядке, возвращаемом итератором. Каждый элемент последовательно присваивается целевому списку по стандартным правилам присваивания (см. [Инструкции присваивания](https://python-all.ru/3.10/reference/simple_stmts.html#assignment)), после чего выполняется блок. Когда элементы исчерпаны (что происходит сразу, когда последовательность пуста или итератор возбуждает исключение [`StopIteration`](https://python-all.ru/3.10/library/exceptions.html#StopIteration)), выполняется блок в предложении `else`, если оно присутствует, и цикл завершается.8788Инструкция [`break`](https://python-all.ru/3.10/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.10/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.10/library/stdtypes.html#range) представляет неизменяемые арифметические последовательности целых чисел. Например, перебор `range(3)` последовательно даёт 0, 1, а затем 2.101102## 8.4. Инструкция `try`103104Инструкция [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) задаёт обработчики исключений и/или код очистки для группы инструкций:105106```107108try_stmt ::= try1_stmt | try2_stmt109try1_stmt ::= "try" ":" suite110 ("except" [expression ["as" identifier]] ":" suite)+111 ["else" ":" suite]112 ["finally" ":" suite]113try2_stmt ::= "try" ":" suite114 "finally" ":" suite115```116117Предложения [`except`](https://python-all.ru/3.10/reference/compound_stmts.html#except) определяют один или несколько обработчиков исключений. Если в предложении [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) не возникает исключения, ни один обработчик не выполняется. Когда в блоке `try` возникает исключение, начинается поиск обработчика. Этот поиск последовательно проверяет предложения except, пока не будет найдено то, которое соответствует исключению. Предложение except без выражения, если присутствует, должно быть последним; оно соответствует любому исключению. Для предложения except с выражением это выражение вычисляется, и предложение соответствует исключению, если результирующий объект «совместим» с исключением. Объект совместим с исключением, если он является классом или [невиртуальным базовым классом](https://python-all.ru/3.10/glossary.html#term-abstract-base-class) объекта исключения, либо кортежем, содержащим элемент, который является классом или невиртуальным базовым классом объекта исключения.118119Если ни одно предложение except не соответствует исключению, поиск обработчика исключений продолжается в окружающем коде и в стеке вызовов. [1](https://python-all.ru/3.10/reference/compound_stmts.html#id16)120121Если вычисление выражения в заголовке предложения except вызывает исключение, исходный поиск обработчика отменяется, и начинается поиск нового исключения в окружающем коде и в стеке вызовов (считается, что исключение вызвано всей инструкцией [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try)).122123Когда найдено подходящее предложение except, исключение присваивается цели, указанной после ключевого слова `as` в этом предложении except (если оно есть), и выполняется блок предложения except. Все предложения except должны иметь исполняемый блок. Когда конец этого блока достигнут, выполнение продолжается обычным образом после всей инструкции try. (Это означает, что если существуют два вложенных обработчика для одного и того же исключения, и исключение возникает в блоке try внутреннего обработчика, внешний обработчик не будет обрабатывать исключение.)124125Когда исключение было присвоено с помощью `as target`, оно очищается в конце предложения except. Это равносильно тому, как если бы126127```python128except E as N:129 foo130```131132было преобразовано в133134```python135except E as N:136 try:137 foo138 finally:139 del N140```141142Это означает, что исключение должно быть присвоено другому имени, чтобы на него можно было ссылаться после предложения except. Исключения очищаются, потому что с прикреплённой к ним трассировкой они образуют циклическую ссылку с кадром стека, удерживая все локальные переменные в этом кадре живыми до следующей сборки мусора.143144Перед выполнением блока предложения except сведения об исключении сохраняются в модуле [`sys`](https://python-all.ru/3.10/library/sys.html#module-sys) и доступны через [`sys.exc_info()`](https://python-all.ru/3.10/library/sys.html#sys.exc_info). [`sys.exc_info()`](https://python-all.ru/3.10/library/sys.html#sys.exc_info) возвращает кортеж из трёх элементов, состоящий из класса исключения, экземпляра исключения и объекта трассировки (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.10/reference/datamodel.html#types)), определяющего точку в программе, где возникло исключение. Сведения об исключении, полученные через [`sys.exc_info()`](https://python-all.ru/3.10/library/sys.html#sys.exc_info), восстанавливают свои предыдущие значения при выходе из обработчика исключения:145146```python147>>> print(sys.exc_info())148(None, None, None)149>>> try:150... raise TypeError151... except:152... print(sys.exc_info())153... try:154... raise ValueError155... except:156... print(sys.exc_info())157... print(sys.exc_info())158...159(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)160(<class 'ValueError'>, ValueError(), <traceback object at 0x10efad040>)161(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)162>>> print(sys.exc_info())163(None, None, None)164```165166Необязательное предложение `else` выполняется, если поток управления покидает блок [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try), не было вызвано исключение и не выполнялся оператор [`return`](https://python-all.ru/3.10/reference/simple_stmts.html#return), [`continue`](https://python-all.ru/3.10/reference/simple_stmts.html#continue) или [`break`](https://python-all.ru/3.10/reference/simple_stmts.html#break). Исключения в предложении `else` не обрабатываются предшествующими предложениями [`except`](https://python-all.ru/3.10/reference/compound_stmts.html#except).167168Если присутствует [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally), он задаёт обработчик «очистки». Выполняется раздел [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try), включая любые разделы [`except`](https://python-all.ru/3.10/reference/compound_stmts.html#except) и `else`. Если в каком-либо из разделов возникает исключение и оно не обработано, исключение временно сохраняется. Затем выполняется раздел `finally`. Если есть сохранённое исключение, оно повторно возбуждается в конце раздела `finally`. Если раздел `finally` возбуждает другое исключение, сохранённое исключение устанавливается как контекст нового исключения. Если раздел `finally` выполняет оператор [`return`](https://python-all.ru/3.10/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.10/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.10/reference/simple_stmts.html#continue), сохранённое исключение отбрасывается:169170```python171>>> def f():172... try:173... 1/0174... finally:175... return 42176...177>>> f()17842179```180181Информация об исключении недоступна программе во время выполнения предложения [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally).182183Когда оператор [`return`](https://python-all.ru/3.10/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.10/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.10/reference/simple_stmts.html#continue) выполняется в блоке [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) оператора `try`…`finally`, предложение [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally) также выполняется «на выходе».184185Возвращаемое значение функции определяется последней выполненной инструкцией [`return`](https://python-all.ru/3.10/reference/simple_stmts.html#return). Поскольку предложение [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally) выполняется всегда, инструкция `return`, выполненная в предложении `finally`, всегда будет последней выполненной:186187```python188>>> def foo():189... try:190... return 'try'191... finally:192... return 'finally'193...194>>> foo()195'finally'196```197198Дополнительную информацию об исключениях можно найти в разделе [Исключения](https://python-all.ru/3.10/reference/executionmodel.html#exceptions), а информация об использовании инструкции [`raise`](https://python-all.ru/3.10/reference/simple_stmts.html#raise) для генерации исключений приведена в разделе [Инструкция raise](https://python-all.ru/3.10/reference/simple_stmts.html#raise).199200Изменено в версии 3.8: До Python 3.8 оператор [`continue`](https://python-all.ru/3.10/reference/simple_stmts.html#continue) был недопустим в предложении [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally) из-за проблемы в реализации.201202## 8.5. Инструкция `with`203204Оператор [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) используется для обёртывания выполнения блока методами, определёнными контекстным менеджером (см. раздел [Контекстные менеджеры оператора with](https://python-all.ru/3.10/reference/datamodel.html#context-managers)). Это позволяет инкапсулировать типичные шаблоны использования [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try)…[`except`](https://python-all.ru/3.10/reference/compound_stmts.html#except)…[`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally) для удобного повторного использования.205206```207208with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite209with_stmt_contents ::= with_item ("," with_item)*210with_item ::= expression ["as" target]211```212213Выполнение оператора [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) с одним «элементом» происходит следующим образом:2142151. Контекстное выражение (выражение, указанное в [`with_item`](https://python-all.ru/3.10/reference/compound_stmts.html#grammar-token-python-grammar-with_item)) вычисляется для получения контекстного менеджера.2162. Метод `__enter__()` контекстного менеджера загружается для последующего использования.2173. Метод `__exit__()` контекстного менеджера загружается для последующего использования.2184. Метод `__enter__()` контекстного менеджера вызывается.2195. Если в операторе [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) была указана цель, возвращаемое значение из `__enter__()` присваивается ей.220221 > **Примечание**222 >223 > Оператор [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) гарантирует, что если метод `__enter__()` возвращается без ошибки, то `__exit__()` всегда будет вызван. Таким образом, если ошибка происходит во время присваивания целевому списку, она обрабатывается так же, как ошибка, возникшая внутри блока. См. шаг 7 ниже.2246. Выполняется блок.2257. Вызывается метод `__exit__()` менеджера контекста. Если исключение вызвало выход из блока, его тип, значение и traceback передаются в качестве аргументов `__exit__()`. В противном случае передаются три аргумента [`None`](https://python-all.ru/3.10/library/constants.html#None).226227 Если блок был завершён из-за исключения и возвращаемое значение метода `__exit__()` было ложным, исключение возбуждается повторно. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается с оператора, следующего за оператором [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with).228229 Если блок был завершён по любой причине, кроме исключения, возвращаемое значение `__exit__()` игнорируется, и выполнение продолжается в обычном месте для данного типа завершения.230231Следующий код:232233```python234with EXPRESSION as TARGET:235 SUITE236```237238семантически эквивалентен следующему:239240```python241manager = (EXPRESSION)242enter = type(manager).__enter__243exit = type(manager).__exit__244value = enter(manager)245hit_except = False246247try:248 TARGET = value249 SUITE250except:251 hit_except = True252 if not exit(manager, *sys.exc_info()):253 raise254finally:255 if not hit_except:256 exit(manager, None, None, None)257```258259При наличии нескольких элементов менеджеры контекста обрабатываются так, как если бы несколько операторов [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) были вложены:260261```python262with A() as a, B() as b:263 SUITE264```265266семантически эквивалентен следующему:267268```python269with A() as a:270 with B() as b:271 SUITE272```273274Можно также записывать многоэлементные менеджеры контекста в несколько строк, если элементы заключены в круглые скобки. Например:275276```python277with (278 A() as a,279 B() as b,280):281 SUITE282```283284Изменено в версии 3.1: Поддержка нескольких выражений контекста.285286Изменено в версии 3.10: Поддержка использования группирующих круглых скобок для разбиения инструкции на несколько строк.287288> **См. также**289>290> **[**PEP 343**](https://python-all.ru/3.10/reference/compound_stmts.html) – Оператор «with»**291>292> Спецификация, предыстория и примеры для инструкции [`with`](https://python-all.ru/3.10/reference/compound_stmts.html#with) в Python.293294## 8.6. Инструкция `match`295296Новое в версии 3.10.297298Оператор match используется для сопоставления с образцом. Синтаксис:299300```301302match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT303subject_expr ::= star_named_expression "," star_named_expressions?304 | named_expression305case_block ::= 'case' patterns [guard] ":" block306```307308> **Примечание**309>310> В этом разделе для обозначения [мягких ключевых слов](https://python-all.ru/3.10/reference/lexical_analysis.html#soft-keywords) используются одинарные кавычки.311312Сопоставление с образцом принимает шаблон (после `case`) и значение-субъект (после `match`). Шаблон (который может содержать подшаблоны) сравнивается со значением-субъектом. Результаты:313314- Успех или неудача сопоставления (также называется успехом или неудачей шаблона).315- Возможное связывание сопоставленных значений с именем. Предварительные условия для этого обсуждаются далее.316317Ключевые слова `match` и `case` являются [мягкими ключевыми словами](https://python-all.ru/3.10/reference/lexical_analysis.html#soft-keywords).318319> **См. также**320>321> - [**PEP 634**](https://python-all.ru/3.10/reference/compound_stmts.html) – Структурное сопоставление с образцом: спецификация322> - [**PEP 636**](https://python-all.ru/3.10/reference/compound_stmts.html) – Структурное сопоставление с образцом: учебное пособие323324### 8.6.1. Обзор325326Вот обзор логического потока оператора match:3273281. Выражение-субъект `subject_expr` вычисляется, и получается результирующее значение-субъект. Если выражение-субъект содержит запятую, кортеж создаётся с использованием [стандартных правил](https://python-all.ru/3.10/library/stdtypes.html#typesseq-tuple).3292. Каждый шаблон в `case_block` пытается совпасть со значением-субъектом. Конкретные правила успеха или неудачи описаны ниже. Попытка сопоставления также может связывать некоторые или все отдельные имена внутри шаблона. Точные правила связывания имён различаются в зависимости от типа шаблона и указаны ниже. **Связывания имён, выполненные во время успешного сопоставления с образцом, переживают выполненный блок и могут использоваться после оператора match**.330331 > > **Примечание**332 > >333 > > При неудачных сопоставлениях некоторые подшаблоны могут оказаться успешными. Не полагайтесь на то, что связывания выполняются для неудачного сопоставления. И наоборот, не полагайтесь на то, что переменные остаются неизменными после неудачного сопоставления. Точное поведение зависит от реализации и может различаться. Это намеренное решение, позволяющее различным реализациям добавлять оптимизации.3343. Если шаблон успешен, вычисляется соответствующее условие (guard), если оно присутствует. В этом случае все связывания имён гарантированно выполнены.335336 - Если условие вычисляется как истина или отсутствует, выполняется `block` внутри `case_block`.337 - В противном случае выполняется попытка следующего `case_block`, как описано выше.338 - Если больше нет блоков case, оператор match завершается.339340> **Примечание**341>342> Пользователям обычно не следует полагаться на то, что шаблон будет вычислен. В зависимости от реализации интерпретатор может кэшировать значения или использовать другие оптимизации, которые пропускают повторные вычисления.343344Пример оператора match:345346```python347>>> flag = False348>>> match (100, 200):349... case (100, 300): # Несоответствие: 200 != 300350... print('Case 1')351... case (100, 200) if flag: # Успешное сопоставление, но страж не сработал352... print('Case 2')353... case (100, y): # Сопоставляется и связывает y с 200354... print(f'Case 3, y: {y}')355... case _: # Шаблон не был задействован356... print('Case 4, I match anything!')357...358Case 3, y: 200359```360361В данном случае `if flag` – это страж. Подробнее об этом в следующем разделе.362363### 8.6.2. Стражи364365```366367guard ::= "if" named_expression368```369370`guard` (являющийся частью `case`) должен успешно выполниться, чтобы код внутри блока `case` был выполнен. Он принимает форму: [`if`](https://python-all.ru/3.10/reference/compound_stmts.html#if) за которым следует выражение.371372Логический ход выполнения блока `case` с `guard` следующий:3733741. Проверка, успешно ли сопоставился шаблон в блоке `case`. Если шаблон не совпал, `guard` не вычисляется и проверяется следующий блок `case`.3752. Если шаблон совпал, вычисляется `guard`.376377 - Если условие `guard` принимает значение true, выбирается блок case.378 - Если условие `guard` принимает значение false, блок case не выбирается.379 - Если при вычислении `guard` возникает исключение, оно всплывает.380381Стражам разрешено иметь побочные эффекты, поскольку они являются выражениями. Вычисление стражей должно выполняться последовательно от первого блока case к последнему, пропуская блоки case, шаблоны которых не совпали все. (Т.е. вычисление стражей должно происходить по порядку.) Вычисление стражей должно останавливаться, как только выбран блок case.382383### 8.6.3. Неопровержимые блоки case384385Неопровержимый блок case – это блок, который совпадает всегда. Оператор match может иметь не более одного неопровержимого блока case, и он должен быть последним.386387Блок case считается неопровержимым, если у него нет стража, а его шаблон неопровержим. Шаблон считается неопровержимым, если из одного только его синтаксиса можно доказать, что он всегда будет успешным. К неопровержимым относятся только следующие шаблоны:388389- [AS-шаблоны](https://python-all.ru/3.10/reference/compound_stmts.html#as-patterns), левая часть которых неопровержима390- [OR-шаблоны](https://python-all.ru/3.10/reference/compound_stmts.html#or-patterns), содержащие хотя бы один неопровержимый шаблон391- [Связывающие шаблоны](https://python-all.ru/3.10/reference/compound_stmts.html#capture-patterns)392- [Шаблоны-заглушки](https://python-all.ru/3.10/reference/compound_stmts.html#wildcard-patterns)393- неопровержимые шаблоны в скобках394395### 8.6.4. Шаблоны396397> **Примечание**398>399> В этом разделе используются обозначения грамматики, выходящие за рамки стандартного EBNF:400>401> - обозначение `SEP.RULE+` является сокращением для `RULE (SEP RULE)*`402> - обозначение `!RULE` является сокращением для негативного опережающего утверждения403404Синтаксис верхнего уровня для `patterns`:405406```407408patterns ::= open_sequence_pattern | pattern409pattern ::= as_pattern | or_pattern410closed_pattern ::= | literal_pattern411 | capture_pattern412 | wildcard_pattern413 | value_pattern414 | group_pattern415 | sequence_pattern416 | mapping_pattern417 | class_pattern418```419420Приведённые ниже описания будут включать описание «простым языком» того, что делает шаблон, в иллюстративных целях (благодарность Раймонду Хеттингеру за документ, вдохновивший большинство описаний). Обратите внимание, что эти описания предназначены исключительно для иллюстрации и **могут не** отражать реальную реализацию. Более того, они не охватывают все допустимые формы.421422#### 8.6.4.1. OR-шаблоны423424OR-шаблон – это два или более шаблона, разделённых вертикальной чертой `|`. Синтаксис:425426```427428or_pattern ::= "|".closed_pattern+429```430431Только последний подшаблон может быть [неопровержимым](https://python-all.ru/3.10/reference/compound_stmts.html#irrefutable-case), и каждый подшаблон должен связывать один и тот же набор имён, чтобы избежать неоднозначности.432433OR-шаблон по очереди сопоставляет каждый из своих подшаблонов с проверяемым значением, пока один из них не совпадёт. Тогда OR-шаблон считается успешным. В противном случае, если ни один из подшаблонов не совпал, OR-шаблон терпит неудачу.434435Простыми словами, `P1 | P2 | ...` попытается сопоставить `P1`; если это не удастся, он попробует сопоставить `P2`, успешно завершаясь при первом же совпадении, иначе завершаясь неудачей.436437#### 8.6.4.2. AS-шаблоны438439AS-шаблон сопоставляет OR-шаблон слева от ключевого слова [`as`](https://python-all.ru/3.10/reference/compound_stmts.html#as) с проверяемым значением. Синтаксис:440441```442443as_pattern ::= or_pattern "as" capture_pattern444```445446Если OR-шаблон терпит неудачу, AS-шаблон также терпит неудачу. В противном случае AS-шаблон связывает проверяемое значение с именем справа от ключевого слова as и завершается успешно. `capture_pattern` не может быть `_`.447448Простыми словами, `P as NAME` совпадает с `P`, и в случае успеха устанавливает `NAME = <subject>`.449450#### 8.6.4.3. Литеральные шаблоны451452Литеральный шаблон соответствует большинству [литералов](https://python-all.ru/3.10/reference/lexical_analysis.html#literals) в Python. Синтаксис:453454```455456literal_pattern ::= signed_number457 | signed_number "+" NUMBER458 | signed_number "-" NUMBER459 | strings460 | "None"461 | "True"462 | "False"463 | signed_number: NUMBER | "-" NUMBER464```465466Правило `strings` и токен `NUMBER` определены в [стандартной грамматике Python](https://python-all.ru/3.10/reference/grammar.html). Строки в тройных кавычках поддерживаются. Сырые строки и байтовые строки поддерживаются. [Форматированные строковые литералы](https://python-all.ru/3.10/reference/lexical_analysis.html#f-strings) не поддерживаются.467468Формы `signed_number '+' NUMBER` и `signed_number '-' NUMBER` предназначены для представления [комплексных чисел](https://python-all.ru/3.10/reference/lexical_analysis.html#imaginary); они требуют действительное число слева и мнимое число справа. Например, `3 + 4j`.469470Простыми словами, `LITERAL` будет успешным только если `<subject> == LITERAL`. Для синглтонов `None`, `True` и `False` используется оператор [`is`](https://python-all.ru/3.10/reference/expressions.html#is).471472#### 8.6.4.4. Захватывающие шаблоны473474Захватывающий шаблон связывает проверяемое значение с именем. Синтаксис:475476```477478capture_pattern ::= !'_' NAME479```480481Одиночное подчеркивание `_` не является захватывающим шаблоном (именно это `!'_'` и выражает). Вместо этого оно обрабатывается как [`wildcard_pattern`](https://python-all.ru/3.10/reference/compound_stmts.html#grammar-token-python-grammar-wildcard_pattern).482483В данном шаблоне конкретное имя может быть связано только один раз. Например, `case x, x: ...` недопустимо, в то время как `case [x] | x: ...` разрешено.484485Захватывающие шаблоны всегда успешны. Связывание следует правилам области видимости, установленным оператором выражений присваивания в [**PEP 572**](https://python-all.ru/3.10/reference/compound_stmts.html); имя становится локальной переменной в ближайшей содержащей функции, если только нет применимого оператора [`global`](https://python-all.ru/3.10/reference/simple_stmts.html#global) или [`nonlocal`](https://python-all.ru/3.10/reference/simple_stmts.html#nonlocal).486487Простыми словами, `NAME` всегда будет успешным и установит `NAME = <subject>`.488489#### 8.6.4.5. Подстановочные шаблоны490491Подстановочный шаблон всегда успешен (совпадает с чем угодно) и не связывает имя. Синтаксис:492493```494495wildcard_pattern ::= '_'496```497498`_` является [мягким ключевым словом](https://python-all.ru/3.10/reference/lexical_analysis.html#soft-keywords) в любом шаблоне, но только внутри шаблонов. Как обычно, это идентификатор, даже внутри `match` проверяемых выражений, `guard` и блоков `case`.499500Простыми словами, `_` всегда будет успешным.501502#### 8.6.4.6. Шаблоны значений503504Шаблон значения представляет именованное значение в Python. Синтаксис:505506```507508value_pattern ::= attr509attr ::= name_or_attr "." NAME510name_or_attr ::= attr | NAME511```512513Точечное имя в шаблоне разрешается с использованием стандартных [правил разрешения имён Python](https://python-all.ru/3.10/reference/executionmodel.html#resolve-names). Шаблон успешен, если найденное значение равно проверяемому значению (с использованием оператора равенства `==`).514515Простыми словами, `NAME1.NAME2` будет успешным только если `<subject> == NAME1.NAME2`516517> **Примечание**518>519> Если одно и то же значение встречается несколько раз в одном и том же операторе match, интерпретатор может кэшировать первое найденное значение и повторно использовать его вместо повторения того же поиска. Этот кэш строго привязан к конкретному выполнению данного оператора match.520521#### 8.6.4.7. Групповые шаблоны522523Групповой шаблон позволяет добавлять круглые скобки вокруг шаблонов, чтобы подчеркнуть предполагаемую группировку. В остальном он не имеет дополнительного синтаксиса. Синтаксис:524525```526527group_pattern ::= "(" pattern ")"528```529530Простыми словами, `(P)` имеет тот же эффект, что и `P`.531532#### 8.6.4.8. Шаблоны последовательностей533534Шаблон последовательности содержит несколько подшаблонов для сопоставления с элементами последовательности. Синтаксис похож на распаковку списка или кортежа.535536```537538sequence_pattern ::= "[" [maybe_sequence_pattern] "]"539 | "(" [open_sequence_pattern] ")"540open_sequence_pattern ::= maybe_star_pattern "," [maybe_sequence_pattern]541maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","?542maybe_star_pattern ::= star_pattern | pattern543star_pattern ::= "*" (capture_pattern | wildcard_pattern)544```545546Нет разницы, используются ли круглые скобки или квадратные скобки для шаблонов последовательностей (т.е. `(...)` vs `[...]`).547548> **Примечание**549>550> Одиночный шаблон, заключенный в круглые скобки без завершающей запятой (например, `(3 | 4)`), является [групповым шаблоном](https://python-all.ru/3.10/reference/compound_stmts.html#group-patterns). В то время как одиночный шаблон в квадратных скобках (например, `[3 | 4]`) по-прежнему является шаблоном последовательности.551552В шаблоне последовательности может быть не более одного звездного подшаблона. Звездный подшаблон может находиться в любой позиции. Если звездный подшаблон отсутствует, шаблон последовательности является шаблоном фиксированной длины; в противном случае это шаблон переменной длины.553554Ниже описан логический поток сопоставления шаблона последовательности с проверяемым значением:5555561. Если проверяемое значение не является последовательностью [2](https://python-all.ru/3.10/reference/compound_stmts.html#id17), шаблон последовательности не срабатывает.5572. Если проверяемое значение является экземпляром `str`, `bytes` или `bytearray`, шаблон последовательности не срабатывает.5583. Последующие шаги зависят от того, имеет ли шаблон последовательности фиксированную или переменную длину.559560 Если шаблон последовательности имеет фиксированную длину:561562 1. Если длина проверяемой последовательности не равна количеству подшаблонов, шаблон последовательности не совпадает.563 2. Подшаблоны в шаблоне последовательности сопоставляются слева направо с соответствующими элементами проверяемой последовательности. Сопоставление прекращается, как только один из подшаблонов не совпадает. Если все подшаблоны успешно совпали со своими элементами, шаблон последовательности считается совпавшим.564565 В противном случае, если шаблон последовательности имеет переменную длину:566567 1. Если длина проверяемой последовательности меньше количества незвёздных подшаблонов, шаблон последовательности не совпадает.568 2. Начальные незвёздные подшаблоны сопоставляются с соответствующими элементами так же, как для последовательностей фиксированной длины.569 3. Если предыдущий шаг выполнен успешно, звёздный подшаблон сопоставляется со списком, сформированным из оставшихся элементов проверяемой последовательности, за исключением элементов, соответствующих незвёздным подшаблонам, которые следуют за звёздным.570 4. Оставшиеся незвёздные подшаблоны сопоставляются с соответствующими элементами проверяемой последовательности так же, как для последовательности фиксированной длины.571572 > **Примечание**573 >574 > Длина последовательности-субъекта получается через [`len()`](https://python-all.ru/3.10/library/functions.html#len) (то есть через протокол `__len__()`). Эта длина может кэшироваться интерпретатором аналогично тому, как [шаблоны значений](https://python-all.ru/3.10/reference/compound_stmts.html#value-patterns).575576Проще говоря, `[P1, P2, P3,` … `, P<N>]` совпадает только в том случае, если выполняются все следующие условия:577578- проверить, что `<subject>` является последовательностью579- `len(subject) == <N>`580- `P1` совпадает с `<subject>[0]` (обратите внимание, что это сопоставление может также связывать имена)581- `P2` совпадает с `<subject>[1]` (обратите внимание, что это сопоставление может также связывать имена)582- … и так далее для соответствующих пар шаблон/элемент.583584#### 8.6.4.9. Шаблоны отображений585586Шаблон отображения содержит один или несколько шаблонов пар ключ-значение. Синтаксис аналогичен созданию словаря. Синтаксис:587588```589590mapping_pattern ::= "{" [items_pattern] "}"591items_pattern ::= ",".key_value_pattern+ ","?592key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern593 | double_star_pattern594double_star_pattern ::= "**" capture_pattern595```596597В шаблоне отображения может быть не более одного шаблона с двойной звёздочкой. Шаблон с двойной звёздочкой должен быть последним подшаблоном в шаблоне отображения.598599Повторяющиеся ключи в шаблонах отображений запрещены. Повторяющиеся литеральные ключи приводят к возникновению [`SyntaxError`](https://python-all.ru/3.10/library/exceptions.html#SyntaxError). Два ключа, которые в остальном имеют одинаковое значение, вызовут [`ValueError`](https://python-all.ru/3.10/library/exceptions.html#ValueError) во время выполнения.600601Ниже описана логика сопоставления шаблона отображения со значением subject:6026031. Если значение subject не является отображением [3](https://python-all.ru/3.10/reference/compound_stmts.html#id18), шаблон отображения не совпадает.6042. Если каждый ключ, указанный в шаблоне отображения, присутствует в отображении subject, и шаблон для каждого ключа совпадает с соответствующим элементом отображения subject, то шаблон отображения считается совпавшим.6053. Если в шаблоне отображения обнаружены повторяющиеся ключи, шаблон считается недействительным. Для повторяющихся литеральных значений возбуждается [`SyntaxError`](https://python-all.ru/3.10/library/exceptions.html#SyntaxError); для именованных ключей с одинаковым значением – [`ValueError`](https://python-all.ru/3.10/library/exceptions.html#ValueError).606607> **Примечание**608>609> Пары ключ-значение сопоставляются с помощью двухаргументной формы метода `get()` объекта-отображения. Соответствующие пары ключ-значение должны уже присутствовать в отображении, а не создаваться на лету через `__missing__()` или `__getitem__()`.610611Проще говоря, `{KEY1: P1, KEY2: P2, ... }` совпадает только при выполнении всех следующих условий:612613- проверить, что `<subject>` является отображением614- `KEY1 in <subject>`615- `P1` соответствует `<subject>[KEY1]`616- … и так далее для соответствующих пар КЛЮЧ/шаблон.617618#### 8.6.4.10. Шаблоны классов619620Шаблон класса представляет класс и его позиционные и именованные аргументы (если есть). Синтаксис:621622```623624class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")"625pattern_arguments ::= positional_patterns ["," keyword_patterns]626 | keyword_patterns627positional_patterns ::= ",".pattern+628keyword_patterns ::= ",".keyword_pattern+629keyword_pattern ::= NAME "=" pattern630```631632Одно и то же имя ключа не должно повторяться в шаблонах классов.633634Ниже описана логика сопоставления шаблона класса со значением subject:6356361. Если `name_or_attr` не является экземпляром встроенного типа [`type`](https://python-all.ru/3.10/library/functions.html#type), возбуждается [`TypeError`](https://python-all.ru/3.10/library/exceptions.html#TypeError).6372. Если проверяемое значение не является экземпляром `name_or_attr` (проверка выполняется с помощью [`isinstance()`](https://python-all.ru/3.10/library/functions.html#isinstance)), то шаблон класса не срабатывает.6383. Если аргументы шаблона отсутствуют, шаблон считается успешным. В противном случае последующие шаги зависят от того, присутствуют ли именованные или позиционные аргументы шаблона.639640 Для ряда встроенных типов (перечисленных ниже) допускается один позиционный подшаблон, который сопоставляется со всем проверяемым значением; для этих типов именованные шаблоны также работают, как и для других типов.641642 Если присутствуют только именованные шаблоны, они обрабатываются следующим образом, по одному:643644 I. Ключевое слово ищется как атрибут у субъекта.645646 > - Если при этом возникает исключение, отличное от [`AttributeError`](https://python-all.ru/3.10/library/exceptions.html#AttributeError), исключение всплывает.647 > - Если при этом возникает [`AttributeError`](https://python-all.ru/3.10/library/exceptions.html#AttributeError), шаблон класса считается несостоявшимся.648 > - В противном случае подшаблон, связанный с именованным шаблоном, сопоставляется со значением атрибута проверяемого значения. Если сопоставление не удаётся, шаблон класса не срабатывает; если успешно, проверка переходит к следующему именованному аргументу.649650 II. Если все шаблоны ключевых слов успешно сопоставлены, шаблон класса считается успешным.651652 Если присутствуют позиционные шаблоны, они преобразуются в именованные шаблоны с помощью атрибута [`__match_args__`](https://python-all.ru/3.10/reference/datamodel.html#object.__match_args__) класса `name_or_attr` перед сопоставлением:653654 I. Вызывается эквивалент `getattr(cls, "__match_args__", ())`.655656 > - Если при этом возникает исключение, оно всплывает.657 > - Если возвращённое значение не является кортежем, преобразование не удаётся, и возбуждается [`TypeError`](https://python-all.ru/3.10/library/exceptions.html#TypeError).658 > - Если количество позиционных шаблонов превышает `len(cls.__match_args__)`, возбуждается [`TypeError`](https://python-all.ru/3.10/library/exceptions.html#TypeError).659 > - В противном случае позиционный шаблон `i` преобразуется в именованный шаблон с использованием `__match_args__[i]` в качестве ключа. `__match_args__[i]` должен быть строкой; в противном случае возбуждается [`TypeError`](https://python-all.ru/3.10/library/exceptions.html#TypeError).660 > - При наличии повторяющихся ключей возбуждается [`TypeError`](https://python-all.ru/3.10/library/exceptions.html#TypeError).661 >662 > > **См. также**663 > >664 > > [Настройка позиционных аргументов в сопоставлении с шаблоном класса](https://python-all.ru/3.10/reference/datamodel.html#class-pattern-matching)665666 **II. Как только все позиционные шаблоны будут преобразованы в шаблоны ключевых слов,**667668 сопоставление продолжается так, как если бы существовали только шаблоны ключевых слов.669670 Для следующих встроенных типов обработка позиционных подшаблонов отличается:671672 - [`bool`](https://python-all.ru/3.10/library/functions.html#bool)673 - [`bytearray`](https://python-all.ru/3.10/library/stdtypes.html#bytearray)674 - [`bytes`](https://python-all.ru/3.10/library/stdtypes.html#bytes)675 - [`dict`](https://python-all.ru/3.10/library/stdtypes.html#dict)676 - [`float`](https://python-all.ru/3.10/library/functions.html#float)677 - [`frozenset`](https://python-all.ru/3.10/library/stdtypes.html#frozenset)678 - [`int`](https://python-all.ru/3.10/library/functions.html#int)679 - [`list`](https://python-all.ru/3.10/library/stdtypes.html#list)680 - [`set`](https://python-all.ru/3.10/library/stdtypes.html#set)681 - [`str`](https://python-all.ru/3.10/library/stdtypes.html#str)682 - [`tuple`](https://python-all.ru/3.10/library/stdtypes.html#tuple)683684 Эти классы принимают один позиционный аргумент, и шаблон в этом случае сопоставляется со всем объектом, а не с атрибутом. Например, `int(0|1)` соответствует значению `0`, но не значению `0.0`.685686Проще говоря, `CLS(P1, attr=P2)` соответствует только в том случае, если происходит следующее:687688- `isinstance(<subject>, CLS)`689- преобразовать `P1` в именованный шаблон с помощью `CLS.__match_args__`690- **Для каждого именованного аргумента `attr=P2`:**691692 - `hasattr(<subject>, "attr")`693 - `P2` соответствует `<subject>.attr`694- … и так далее для соответствующей пары именованный аргумент/шаблон.695696> **См. также**697>698> - [**PEP 634**](https://python-all.ru/3.10/reference/compound_stmts.html) – Структурное сопоставление с образцом: спецификация699> - [**PEP 636**](https://python-all.ru/3.10/reference/compound_stmts.html) – Структурное сопоставление с образцом: учебное пособие700701## 8.7. Определения функций702703Определение функции создаёт объект пользовательской функции (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.10/reference/datamodel.html#types)):704705```706707funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"708 ["->" expression] ":" suite709decorators ::= decorator+710decorator ::= "@" assignment_expression NEWLINE711parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]712 | parameter_list_no_posonly713parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]714 | parameter_list_starargs715parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]716 | "**" parameter [","]717parameter ::= identifier [":" expression]718defparameter ::= parameter ["=" expression]719funcname ::= identifier720```721722Определение функции – это исполняемый оператор. Его выполнение связывает имя функции в текущей локальной области видимости с объектом функции (обёрткой над исполняемым кодом функции). Этот объект функции содержит ссылку на текущую глобальную область видимости, которая будет использоваться при вызове функции.723724Определение функции не выполняет тело функции; оно выполняется только при вызове функции. [4](https://python-all.ru/3.10/reference/compound_stmts.html#id19)725726Определение функции может быть обёрнуто одним или несколькими выражениями [декоратора](https://python-all.ru/3.10/glossary.html#term-decorator). Выражения декоратора вычисляются при определении функции в области видимости, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращённое значение связывается с именем функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код727728```python729@f1(arg)730@f2731def func(): pass732```733734примерно эквивалентно735736```python737def func(): pass738func = f1(arg)(f2(func))739```740741за исключением того, что исходная функция не привязывается временно к имени `func`.742743Изменено в версии 3.9: Функции могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.10/reference/expressions.html#grammar-token-python-grammar-assignment_expression). Ранее грамматика была гораздо более строгой; подробнее см. [**PEP 614**](https://python-all.ru/3.10/reference/compound_stmts.html).744745Когда один или несколько [параметров](https://python-all.ru/3.10/glossary.html#term-parameter) имеют вид *параметр* `=` *выражение*, говорят, что функция имеет «значения параметров по умолчанию». Для параметра со значением по умолчанию соответствующий [аргумент](https://python-all.ru/3.10/glossary.html#term-argument) может быть опущен при вызове, и в этом случае подставляется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры до «`*`» также должны иметь значение по умолчанию – это синтаксическое ограничение, которое не отражено в грамматике.746747**Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции.** Это означает, что выражение вычисляется один раз, когда функция определяется, и одно и то же «предварительно вычисленное» значение используется при каждом вызове. Это особенно важно понимать, когда значение параметра по умолчанию является изменяемым объектом, например списком или словарём: если функция изменяет объект (например, добавляет элемент в список), то значение параметра по умолчанию фактически изменяется. Обычно это не то, что предполагалось. Один из способов обойти это – использовать `None` в качестве значения по умолчанию и явно проверять его в теле функции, например:748749```python750def whats_on_the_telly(penguin=None):751 if penguin is None:752 penguin = []753 penguin.append("property of the zoo")754 return penguin755```756757Семантика вызова функций подробно описана в разделе [Calls](https://python-all.ru/3.10/reference/expressions.html#calls). Вызов функции всегда присваивает значения всем параметрам, указанным в списке параметров, либо из позиционных аргументов, либо из именованных аргументов, либо из значений по умолчанию. Если присутствует форма «`*identifier`», она инициализируется кортежем, принимающим все лишние позиционные параметры, по умолчанию пустой кортеж. Если присутствует форма «`**identifier`», она инициализируется новым упорядоченным отображением, принимающим все лишние именованные аргументы, по умолчанию новым пустым отображением того же типа. Параметры после «`*`» или «`*identifier`» являются параметрами только для ключевых слов и могут передаваться только именованными аргументами. Параметры до «`/`» являются параметрами только для позиции и могут передаваться только позиционными аргументами.758759Изменено в версии 3.8: Синтаксис параметра функции `/` может использоваться для обозначения позиционных параметров. Подробнее см. [**PEP 570**](https://python-all.ru/3.10/reference/compound_stmts.html).760761Параметры могут иметь [аннотацию](https://python-all.ru/3.10/glossary.html#term-function-annotation) вида «`: expression`» после имени параметра. Любой параметр может иметь аннотацию, даже параметры вида `*identifier` или `**identifier`. Функции могут иметь аннотацию возврата вида «`-> expression`» после списка параметров. Эти аннотации могут быть любым допустимым выражением Python. Наличие аннотаций не меняет семантику функции. Значения аннотаций доступны как значения словаря, ключами которого являются имена параметров, в атрибуте `__annotations__` объекта функции. Если используется импорт `annotations` из [`__future__`](https://python-all.ru/3.10/library/__future__.html#module-__future__), аннотации сохраняются в виде строк во время выполнения, что позволяет отложить их вычисление. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут вычисляться в порядке, отличном от порядка их появления в исходном коде.762763Также можно создавать анонимные функции (функции, не привязанные к имени) для немедленного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе [Lambdas](https://python-all.ru/3.10/reference/expressions.html#lambda). Обратите внимание, что лямбда-выражение – это всего лишь сокращение для упрощённого определения функции; функцию, определённую в инструкции «[`def`](https://python-all.ru/3.10/reference/compound_stmts.html#def)», можно передавать или присваивать другому имени так же, как функцию, определённую лямбда-выражением. Форма «`def`» на самом деле более мощная, поскольку позволяет выполнять несколько инструкций и аннотаций.764765**Замечание программисту:** Функции – объекты первого класса. Инструкция «`def`», выполненная внутри определения функции, определяет локальную функцию, которую можно вернуть или передать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробнее см. раздел [Naming and binding](https://python-all.ru/3.10/reference/executionmodel.html#naming).766767> **См. также**768>769> **[**PEP 3107**](https://python-all.ru/3.10/reference/compound_stmts.html) – Аннотации функций**770>771> Оригинальная спецификация аннотаций функций.772>773> **[**PEP 484**](https://python-all.ru/3.10/reference/compound_stmts.html) – Аннотации типов**774>775> Определение стандартного значения аннотаций: подсказки типов.776>777> **[**PEP 526**](https://python-all.ru/3.10/reference/compound_stmts.html) - Синтаксис аннотаций переменных**778>779> Возможность аннотировать типы объявлений переменных, включая переменные класса и переменные экземпляра780>781> **[**PEP 563**](https://python-all.ru/3.10/reference/compound_stmts.html) – Отложенное вычисление аннотаций**782>783> Поддержка прямых ссылок в аннотациях путём сохранения аннотаций в строковом виде во время выполнения вместо немедленного вычисления.784785## 8.8. Определения классов786787Определение класса создаёт объект класса (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.10/reference/datamodel.html#types)):788789```790791classdef ::= [decorators] "class" classname [inheritance] ":" suite792inheritance ::= "(" [argument_list] ")"793classname ::= identifier794```795796Определение класса – это исполняемая инструкция. Список наследования обычно содержит список базовых классов (см. [Метаклассы](https://python-all.ru/3.10/reference/datamodel.html#metaclasses) для более продвинутого использования), поэтому каждый элемент списка должен вычисляться в объект класса, который допускает создание подклассов. Классы без списка наследования по умолчанию наследуют от базового класса [`object`](https://python-all.ru/3.10/library/functions.html#object); следовательно,797798```python799class Foo:800 pass801```802803эквивалентна804805```python806class Foo(object):807 pass808```809810Затем тело класса выполняется в новом фрейме выполнения (см. [Naming and binding](https://python-all.ru/3.10/reference/executionmodel.html#naming)), используя только что созданное локальное пространство имён и исходное глобальное пространство имён. (Обычно тело содержит в основном определения функций.) Когда выполнение тела класса завершается, его фрейм выполнения отбрасывается, но локальное пространство имён сохраняется. [5](https://python-all.ru/3.10/reference/compound_stmts.html#id20) Затем создаётся объект класса с использованием списка наследования для базовых классов и сохранённого локального пространства имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.811812Порядок, в котором атрибуты определяются в теле класса, сохраняется в `__dict__` нового класса. Обратите внимание, что это надёжно только сразу после создания класса и только для классов, определённых с использованием синтаксиса определения.813814Создание класса можно сильно настраивать с помощью [метаклассов](https://python-all.ru/3.10/reference/datamodel.html#metaclasses).815816Классы также могут быть декорированы: так же, как и при декорировании функций,817818```python819@f1(arg)820@f2821class Foo: pass822```823824примерно эквивалентно825826```python827class Foo: pass828Foo = f1(arg)(f2(Foo))829```830831Правила вычисления выражений декораторов такие же, как и для декораторов функций. Затем результат привязывается к имени класса.832833Изменено в версии 3.9: Классы могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.10/reference/expressions.html#grammar-token-python-grammar-assignment_expression). Ранее грамматика была гораздо более строгой; подробнее см. [**PEP 614**](https://python-all.ru/3.10/reference/compound_stmts.html).834835**Замечание для программиста:** Переменные, определённые в определении класса, являются атрибутами класса; они разделяются экземплярами. Атрибуты экземпляра можно задать в методе с помощью `self.name = value`. Как атрибуты класса, так и атрибуты экземпляра доступны через запись “`self.name`”, и при таком обращении атрибут экземпляра скрывает атрибут класса с тем же именем. Атрибуты класса могут использоваться как значения по умолчанию для атрибутов экземпляра, но использование изменяемых значений может привести к неожиданным результатам. [Дескрипторы](https://python-all.ru/3.10/reference/datamodel.html#descriptors) можно использовать для создания переменных экземпляра с другими деталями реализации.836837> **См. также**838>839> **[**PEP 3115**](https://python-all.ru/3.10/reference/compound_stmts.html) – Метаклассы в Python 3000**840>841> Предложение, изменившее объявление метаклассов на текущий синтаксис, и семантику того, как конструируются классы с метаклассами.842>843> **[**PEP 3129**](https://python-all.ru/3.10/reference/compound_stmts.html) - Декораторы классов**844>845> Предложение, добавившее декораторы классов. Декораторы функций и методов были введены в [**PEP 318**](https://python-all.ru/3.10/reference/compound_stmts.html).846847## 8.9. Корутины848849Новое в версии 3.5.850851### 8.9.1. Определение корутинной функции852853```854855async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"856 ["->" expression] ":" suite857```858859Выполнение корутин Python может приостанавливаться и возобновляться во многих точках (см. [корутина](https://python-all.ru/3.10/glossary.html#term-coroutine)). Выражения [`await`](https://python-all.ru/3.10/reference/expressions.html#await), [`async for`](https://python-all.ru/3.10/reference/compound_stmts.html#async-for) и [`async with`](https://python-all.ru/3.10/reference/compound_stmts.html#async-with) можно использовать только в теле корутинной функции.860861Функции, определённые с синтаксисом `async def`, всегда являются корутинными функциями, даже если они не содержат ключевых слов `await` или `async`.862863Использование выражения `yield from` в теле корутинной функции является [`SyntaxError`](https://python-all.ru/3.10/library/exceptions.html#SyntaxError).864865Пример корутинной функции:866867```python868async def func(param1, param2):869 do_stuff()870 await some_coroutine()871```872873Изменено в версии 3.7: `await` и `async` теперь являются ключевыми словами; ранее они рассматривались как таковые только внутри тела корутинной функции.874875### 8.9.2. Инструкция `async for`876877```878879async_for_stmt ::= "async" for_stmt880```881882[Асинхронный итерируемый объект](https://python-all.ru/3.10/glossary.html#term-asynchronous-iterable) предоставляет метод `__aiter__`, который напрямую возвращает [асинхронный итератор](https://python-all.ru/3.10/glossary.html#term-asynchronous-iterator), способный вызывать асинхронный код в своём методе `__anext__`.883884Инструкция `async for` обеспечивает удобную итерацию по асинхронным итерируемым объектам.885886Следующий код:887888```python889async for TARGET in ITER:890 SUITE891else:892 SUITE2893```894895Семантически эквивалентен следующему:896897```python898iter = (ITER)899iter = type(iter).__aiter__(iter)900running = True901902while running:903 try:904 TARGET = await type(iter).__anext__(iter)905 except StopAsyncIteration:906 running = False907 else:908 SUITE909else:910 SUITE2911```912913См. также [`__aiter__()`](https://python-all.ru/3.10/reference/datamodel.html#object.__aiter__) и [`__anext__()`](https://python-all.ru/3.10/reference/datamodel.html#object.__anext__) для подробностей.914915Использование инструкции `async for` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.10/library/exceptions.html#SyntaxError).916917### 8.9.3. Инструкция `async with`918919```920921async_with_stmt ::= "async" with_stmt922```923924[Асинхронный менеджер контекста](https://python-all.ru/3.10/glossary.html#term-asynchronous-context-manager) – это [менеджер контекста](https://python-all.ru/3.10/glossary.html#term-context-manager), который может приостанавливать выполнение в своих методах *входа* и *выхода*.925926Следующий код:927928```python929async with EXPRESSION as TARGET:930 SUITE931```932933семантически эквивалентен следующему:934935```python936manager = (EXPRESSION)937aenter = type(manager).__aenter__938aexit = type(manager).__aexit__939value = await aenter(manager)940hit_except = False941942try:943 TARGET = value944 SUITE945except:946 hit_except = True947 if not await aexit(manager, *sys.exc_info()):948 raise949finally:950 if not hit_except:951 await aexit(manager, None, None, None)952```953954См. также [`__aenter__()`](https://python-all.ru/3.10/reference/datamodel.html#object.__aenter__) и [`__aexit__()`](https://python-all.ru/3.10/reference/datamodel.html#object.__aexit__) для подробностей.955956Использование инструкции `async with` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.10/library/exceptions.html#SyntaxError).957958> **См. также**959>960> **[**PEP 492**](https://python-all.ru/3.10/reference/compound_stmts.html) - Корутины с синтаксисом async и await**961>962> Предложение, которое сделало корутины полноценной самостоятельной концепцией в Python и добавило поддерживающий синтаксис.963964Сноски965966**[1](https://python-all.ru/3.10/reference/compound_stmts.html#id1)**967968Исключение распространяется по стеку вызовов, если только не встретится предложение [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally), которое в свою очередь возбуждает другое исключение. Это новое исключение приводит к потере старого.969970**[2](https://python-all.ru/3.10/reference/compound_stmts.html#id10)**971972В сопоставлении с образцом последовательность определяется как одно из следующего:973974> - класс, который наследует от [`collections.abc.Sequence`](https://python-all.ru/3.10/library/collections.abc.html#collections.abc.Sequence)975> - класс Python, который был зарегистрирован как [`collections.abc.Sequence`](https://python-all.ru/3.10/library/collections.abc.html#collections.abc.Sequence)976> - встроенный класс, у которого установлен бит [`Py_TPFLAGS_SEQUENCE`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_SEQUENCE) (в CPython)977> - класс, который наследует от любого из вышеперечисленных978979Следующие классы стандартной библиотеки являются последовательностями:980981> - [`array.array`](https://python-all.ru/3.10/library/array.html#array.array)982> - [`collections.deque`](https://python-all.ru/3.10/library/collections.html#collections.deque)983> - [`list`](https://python-all.ru/3.10/library/stdtypes.html#list)984> - [`memoryview`](https://python-all.ru/3.10/library/stdtypes.html#memoryview)985> - [`range`](https://python-all.ru/3.10/library/stdtypes.html#range)986> - [`tuple`](https://python-all.ru/3.10/library/stdtypes.html#tuple)987988> **Примечание**989>990> Проверяемые значения типов `str`, `bytes` и `bytearray` не соответствуют шаблонам последовательностей.991992**[3](https://python-all.ru/3.10/reference/compound_stmts.html#id12)**993994В сопоставлении с образцом отображение определяется как одно из следующего:995996> - класс, который наследует от [`collections.abc.Mapping`](https://python-all.ru/3.10/library/collections.abc.html#collections.abc.Mapping)997> - класс Python, который был зарегистрирован как [`collections.abc.Mapping`](https://python-all.ru/3.10/library/collections.abc.html#collections.abc.Mapping)998> - встроенный класс, у которого установлен бит [`Py_TPFLAGS_MAPPING`](https://python-all.ru/3.10/c-api/typeobj.html#Py_TPFLAGS_MAPPING) (в CPython)999> - класс, который наследует от любого из вышеперечисленных10001001Классы стандартной библиотеки [`dict`](https://python-all.ru/3.10/library/stdtypes.html#dict) и [`types.MappingProxyType`](https://python-all.ru/3.10/library/types.html#types.MappingProxyType) являются отображениями.10021003**[4](https://python-all.ru/3.10/reference/compound_stmts.html#id14)**10041005Строковый литерал, появляющийся как первая инструкция в теле функции, преобразуется в атрибут `__doc__` функции и, следовательно, в [докстринг](https://python-all.ru/3.10/glossary.html#term-docstring) функции.10061007**[5](https://python-all.ru/3.10/reference/compound_stmts.html#id15)**10081009Строковый литерал, появляющийся в качестве первого оператора в теле класса, преобразуется в элемент `__doc__` пространства имён и, следовательно, в [докстринг](https://python-all.ru/3.10/glossary.html#term-docstring) класса.1010