compound_stmts.md
1> **Источник:** https://python-all.ru/3.9/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.9/reference/compound_stmts.html#if), [`while`](https://python-all.ru/3.9/reference/compound_stmts.html#while) и [`for`](https://python-all.ru/3.9/reference/compound_stmts.html#for) реализуют традиционные конструкции управления потоком. [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try) задаёт обработчики исключений и/или код очистки для группы инструкций, а инструкция [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) позволяет выполнять код инициализации и финализации вокруг блока кода. Определения функций и классов также синтаксически являются составными инструкциями.1213Составная инструкция состоит из одного или нескольких «предложений». Предложение состоит из заголовка и «набора инструкций». Заголовки предложений одной составной инструкции находятся на одном уровне отступа. Каждый заголовок предложения начинается с уникального ключевого слова и завершается двоеточием. Набор инструкций – это группа инструкций, управляемая предложением. Набор инструкций может состоять из одной или нескольких простых инструкций, разделённых точкой с запятой, на той же строке, что и заголовок, после его двоеточия, или из одной или нескольких инструкций с отступом на последующих строках. Только вторая форма набора инструкций может содержать вложенные составные инструкции; следующий пример недопустим, в основном потому, что было бы непонятно, к какому предложению [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) будет относиться последующее предложение [`else`](https://python-all.ru/3.9/reference/compound_stmts.html#else):1415```python16if test1: if test2: print(x)17```1819Также обратите внимание, что точка с запятой связывает сильнее, чем двоеточие в этом контексте, так что в следующем примере выполняются либо все вызовы [`print()`](https://python-all.ru/3.9/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 | funcdef35 | classdef36 | async_with_stmt37 | async_for_stmt38 | async_funcdef39suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT40statement ::= stmt_list NEWLINE | compound_stmt41stmt_list ::= simple_stmt (";" simple_stmt)* [";"]42```4344Обратите внимание, что инструкции всегда заканчиваются `NEWLINE`, за которым может следовать `DEDENT`. Также обратите внимание, что опциональные продолжения всегда начинаются с ключевого слова, которое не может начинать инструкцию, поэтому неоднозначностей нет (проблема «висячего [`else`](https://python-all.ru/3.9/reference/compound_stmts.html#else)» решается в Python требованием, чтобы вложенные инструкции [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) имели отступ).4546Форматирование грамматических правил в следующих разделах помещает каждое предложение на отдельную строку для ясности.4748## 8.1. Инструкция `if`4950Инструкция [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) используется для условного выполнения:5152```5354if_stmt ::= "if" assignment_expression ":" suite55 ("elif" assignment_expression ":" suite)*56 ["else" ":" suite]57```5859Он выбирает ровно один из наборов инструкций, вычисляя выражения одно за другим, пока одно из них не окажется истинным (см. раздел [Булевы операции](https://python-all.ru/3.9/reference/expressions.html#booleans) для определения истины и лжи); затем этот набор выполняется (и никакая другая часть инструкции [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) не выполняется и не вычисляется). Если все выражения ложны, выполняется набор инструкций предложения [`else`](https://python-all.ru/3.9/reference/compound_stmts.html#else), если оно присутствует.6061## 8.2. Инструкция `while`6263Инструкция [`while`](https://python-all.ru/3.9/reference/compound_stmts.html#while) используется для повторного выполнения, пока выражение истинно:6465```6667while_stmt ::= "while" assignment_expression ":" suite68 ["else" ":" suite]69```7071Эта инструкция многократно проверяет выражение и, если оно истинно, выполняет первый набор инструкций; если выражение ложно (возможно, при первой проверке), то набор инструкций предложения `else`, если оно присутствует, выполняется, и цикл завершается.7273Инструкция [`break`](https://python-all.ru/3.9/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue), выполненная в первом наборе, пропускает оставшуюся часть набора и возвращается к проверке выражения.7475## 8.3. Инструкция `for`7677Инструкция [`for`](https://python-all.ru/3.9/reference/compound_stmts.html#for) используется для перебора элементов последовательности (например, строки, кортежа или списка) или другого итерируемого объекта:7879```8081for_stmt ::= "for" target_list "in" expression_list ":" suite82 ["else" ":" suite]83```8485Список выражений вычисляется один раз; он должен давать итерируемый объект. Итератор создаётся для результата `expression_list`. Затем блок инструкций выполняется один раз для каждого элемента, предоставленного итератором, в порядке, возвращаемом итератором. Каждый элемент последовательно присваивается целевому списку по стандартным правилам присваивания (см. [Инструкции присваивания](https://python-all.ru/3.9/reference/simple_stmts.html#assignment)), после чего выполняется блок. Когда элементы исчерпаны (что происходит сразу, когда последовательность пуста или итератор возбуждает исключение [`StopIteration`](https://python-all.ru/3.9/library/exceptions.html#StopIteration)), выполняется блок в предложении `else`, если оно присутствует, и цикл завершается.8687Инструкция [`break`](https://python-all.ru/3.9/reference/simple_stmts.html#break), выполненная в первом наборе, завершает цикл, не выполняя набор инструкций предложения `else`. Инструкция [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue), выполненная в первом наборе, пропускает оставшуюся часть набора и продолжает со следующим элементом, или с предложением `else`, если следующего элемента нет.8889Цикл for выполняет присваивания переменным в целевом списке. Это перезаписывает все предыдущие присваивания этим переменным, включая те, что были сделаны в наборе инструкций цикла for:9091```python92for i in range(10):93 print(i)94 i = 5 # это не повлияет на цикл for95 # потому что i будет перезаписано следующим96 # индексом в range97```9899Имена в списке целей не удаляются по завершении цикла, но если последовательность пуста, они вообще не будут присвоены циклом. Подсказка: встроенная функция [`range()`](https://python-all.ru/3.9/library/stdtypes.html#range) возвращает итератор целых чисел, подходящий для имитации эффекта `for i := a to b do` в Pascal; например, `list(range(3))` возвращает список `[0, 1, 2]`.100101> **Примечание**102>103> Существует тонкость, когда последовательность изменяется циклом (это возможно только для изменяемых последовательностей, например списков). Внутренний счётчик используется для отслеживания того, какой элемент будет обработан следующим, и он увеличивается на каждой итерации. Когда этот счётчик достигает длины последовательности, цикл завершается. Это означает, что если блок удаляет текущий (или предыдущий) элемент из последовательности, следующий элемент будет пропущен (поскольку он получает индекс текущего элемента, который уже был обработан). Аналогично, если блок вставляет элемент в последовательность перед текущим, текущий элемент будет обработан снова при следующем проходе цикла. Это может привести к неприятным ошибкам, которых можно избежать, создав временную копию с помощью среза всей последовательности, например,104>105> ```python106> for x in a[:]:107> if x < 0: a.remove(x)108> ```109110## 8.4. Инструкция `try`111112Инструкция [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try) задаёт обработчики исключений и/или код очистки для группы инструкций:113114```115116try_stmt ::= try1_stmt | try2_stmt117try1_stmt ::= "try" ":" suite118 ("except" [expression ["as" identifier]] ":" suite)+119 ["else" ":" suite]120 ["finally" ":" suite]121try2_stmt ::= "try" ":" suite122 "finally" ":" suite123```124125Предложения [`except`](https://python-all.ru/3.9/reference/compound_stmts.html#except) определяют один или несколько обработчиков исключений. Если в предложении [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try) не возникает исключения, ни один обработчик не выполняется. Когда в блоке `try` возникает исключение, начинается поиск обработчика. Этот поиск последовательно проверяет предложения except, пока не будет найдено то, которое соответствует исключению. Предложение except без выражения, если присутствует, должно быть последним; оно соответствует любому исключению. Для предложения except с выражением это выражение вычисляется, и предложение соответствует исключению, если результирующий объект «совместим» с исключением. Объект совместим с исключением, если он является классом или [невиртуальным базовым классом](https://python-all.ru/3.9/glossary.html#term-abstract-base-class) объекта исключения, либо кортежем, содержащим элемент, который является классом или невиртуальным базовым классом объекта исключения.126127Если ни одно предложение except не соответствует исключению, поиск обработчика исключений продолжается в окружающем коде и в стеке вызовов. [1](https://python-all.ru/3.9/reference/compound_stmts.html#id4)128129Если вычисление выражения в заголовке предложения except вызывает исключение, исходный поиск обработчика отменяется, и начинается поиск нового исключения в окружающем коде и в стеке вызовов (считается, что исключение вызвано всей инструкцией [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try)).130131Когда найдено подходящее предложение except, исключение присваивается цели, указанной после ключевого слова `as` в этом предложении except (если оно есть), и выполняется блок предложения except. Все предложения except должны иметь исполняемый блок. Когда конец этого блока достигнут, выполнение продолжается обычным образом после всей инструкции try. (Это означает, что если существуют два вложенных обработчика для одного и того же исключения, и исключение возникает в блоке try внутреннего обработчика, внешний обработчик не будет обрабатывать исключение.)132133Когда исключение было присвоено с помощью `as target`, оно очищается в конце предложения except. Это равносильно тому, как если бы134135```python136except E as N:137 foo138```139140было преобразовано в141142```python143except E as N:144 try:145 foo146 finally:147 del N148```149150Это означает, что исключение должно быть присвоено другому имени, чтобы на него можно было ссылаться после предложения except. Исключения очищаются, потому что с прикреплённой к ним трассировкой они образуют циклическую ссылку с кадром стека, удерживая все локальные переменные в этом кадре живыми до следующей сборки мусора.151152Перед выполнением блока except-предложения подробности об исключении сохраняются в модуле [`sys`](https://python-all.ru/3.9/library/sys.html#module-sys) и могут быть получены через [`sys.exc_info()`](https://python-all.ru/3.9/library/sys.html#sys.exc_info). [`sys.exc_info()`](https://python-all.ru/3.9/library/sys.html#sys.exc_info) возвращает кортеж из трёх элементов: класс исключения, экземпляр исключения и объект трассировки (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.9/reference/datamodel.html#types)), указывающий точку программы, где произошло исключение. Значения [`sys.exc_info()`](https://python-all.ru/3.9/library/sys.html#sys.exc_info) восстанавливаются до предыдущих (до вызова) при возврате из функции, обработавшей исключение.153154Необязательное предложение `else` выполняется, если поток управления покидает блок [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try), не было вызвано исключение и не выполнялся оператор [`return`](https://python-all.ru/3.9/reference/simple_stmts.html#return), [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue) или [`break`](https://python-all.ru/3.9/reference/simple_stmts.html#break). Исключения в предложении `else` не обрабатываются предшествующими предложениями [`except`](https://python-all.ru/3.9/reference/compound_stmts.html#except).155156Если присутствует [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally), он задаёт обработчик «очистки». Выполняется раздел [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try), включая любые разделы [`except`](https://python-all.ru/3.9/reference/compound_stmts.html#except) и `else`. Если в каком-либо из разделов возникает исключение и оно не обработано, исключение временно сохраняется. Затем выполняется раздел `finally`. Если есть сохранённое исключение, оно повторно возбуждается в конце раздела `finally`. Если раздел `finally` возбуждает другое исключение, сохранённое исключение устанавливается как контекст нового исключения. Если раздел `finally` выполняет оператор [`return`](https://python-all.ru/3.9/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.9/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue), сохранённое исключение отбрасывается:157158```python159>>> def f():160... try:161... 1/0162... finally:163... return 42164...165>>> f()16642167```168169Информация об исключении недоступна программе во время выполнения предложения [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally).170171Когда оператор [`return`](https://python-all.ru/3.9/reference/simple_stmts.html#return), [`break`](https://python-all.ru/3.9/reference/simple_stmts.html#break) или [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue) выполняется в блоке [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try) оператора `try`…`finally`, предложение [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally) также выполняется «на выходе».172173Возвращаемое значение функции определяется последней выполненной инструкцией [`return`](https://python-all.ru/3.9/reference/simple_stmts.html#return). Поскольку предложение [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally) выполняется всегда, инструкция `return`, выполненная в предложении `finally`, всегда будет последней выполненной:174175```python176>>> def foo():177... try:178... return 'try'179... finally:180... return 'finally'181...182>>> foo()183'finally'184```185186Дополнительную информацию об исключениях можно найти в разделе [Исключения](https://python-all.ru/3.9/reference/executionmodel.html#exceptions), а информация об использовании инструкции [`raise`](https://python-all.ru/3.9/reference/simple_stmts.html#raise) для генерации исключений приведена в разделе [Инструкция raise](https://python-all.ru/3.9/reference/simple_stmts.html#raise).187188Изменено в версии 3.8: До Python 3.8 оператор [`continue`](https://python-all.ru/3.9/reference/simple_stmts.html#continue) был недопустим в предложении [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally) из-за проблемы в реализации.189190## 8.5. Инструкция `with`191192Оператор [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) используется для обёртывания выполнения блока методами, определёнными контекстным менеджером (см. раздел [Контекстные менеджеры оператора with](https://python-all.ru/3.9/reference/datamodel.html#context-managers)). Это позволяет инкапсулировать типичные шаблоны использования [`try`](https://python-all.ru/3.9/reference/compound_stmts.html#try)…[`except`](https://python-all.ru/3.9/reference/compound_stmts.html#except)…[`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally) для удобного повторного использования.193194```195196with_stmt ::= "with" with_item ("," with_item)* ":" suite197with_item ::= expression ["as" target]198```199200Выполнение оператора [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) с одним «элементом» происходит следующим образом:2012021. Контекстное выражение (выражение, указанное в [`with_item`](https://python-all.ru/3.9/reference/compound_stmts.html#grammar-token-with-item)) вычисляется для получения менеджера контекста.2032. Метод [`__enter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__enter__) контекстного менеджера загружается для последующего использования.2043. Метод [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__) контекстного менеджера загружается для последующего использования.2054. Метод [`__enter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__enter__) контекстного менеджера вызывается.2065. Если в операторе [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) была указана цель, возвращаемое значение из [`__enter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__enter__) присваивается ей.207208 > **Примечание**209 >210 > Инструкция [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) гарантирует, что если метод [`__enter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__enter__) завершится без ошибки, то [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__) будет вызван обязательно. Таким образом, если во время присваивания списку целей произойдет ошибка, она будет обработана так же, как ошибка, возникшая внутри блока. См. шаг 6 ниже.2116. Выполняется блок.2127. Вызывается метод [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__) менеджера контекста. Если исключение вызвало выход из блока, его тип, значение и traceback передаются в качестве аргументов [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__). В противном случае передаются три аргумента [`None`](https://python-all.ru/3.9/library/constants.html#None).213214 Если блок был завершён из-за исключения и возвращаемое значение метода [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__) было ложным, исключение возбуждается повторно. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается с оператора, следующего за оператором [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with).215216 Если блок был завершён по любой причине, кроме исключения, возвращаемое значение [`__exit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__exit__) игнорируется, и выполнение продолжается в обычном месте для данного типа завершения.217218Следующий код:219220```python221with EXPRESSION as TARGET:222 SUITE223```224225семантически эквивалентен следующему:226227```python228manager = (EXPRESSION)229enter = type(manager).__enter__230exit = type(manager).__exit__231value = enter(manager)232hit_except = False233234try:235 TARGET = value236 SUITE237except:238 hit_except = True239 if not exit(manager, *sys.exc_info()):240 raise241finally:242 if not hit_except:243 exit(manager, None, None, None)244```245246При наличии нескольких элементов менеджеры контекста обрабатываются так, как если бы несколько операторов [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) были вложены:247248```python249with A() as a, B() as b:250 SUITE251```252253семантически эквивалентен следующему:254255```python256with A() as a:257 with B() as b:258 SUITE259```260261Изменено в версии 3.1: Поддержка нескольких выражений контекста.262263> **См. также**264>265> **[**PEP 343**](https://python-all.ru/3.9/reference/compound_stmts.html) – Оператор «with»**266>267> Спецификация, предыстория и примеры для инструкции [`with`](https://python-all.ru/3.9/reference/compound_stmts.html#with) в Python.268269## 8.6. Определения функций270271Определение функции создаёт объект пользовательской функции (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.9/reference/datamodel.html#types)):272273```274275funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"276 ["->" expression] ":" suite277decorators ::= decorator+278decorator ::= "@" assignment_expression NEWLINE279parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]280 | parameter_list_no_posonly281parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]282 | parameter_list_starargs283parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]284 | "**" parameter [","]285parameter ::= identifier [":" expression]286defparameter ::= parameter ["=" expression]287funcname ::= identifier288```289290Определение функции – это исполняемый оператор. Его выполнение связывает имя функции в текущей локальной области видимости с объектом функции (обёрткой над исполняемым кодом функции). Этот объект функции содержит ссылку на текущую глобальную область видимости, которая будет использоваться при вызове функции.291292Определение функции не выполняет тело функции; оно выполняется только при вызове функции. [2](https://python-all.ru/3.9/reference/compound_stmts.html#id5)293294Определение функции может быть обёрнуто одним или несколькими выражениями [декоратора](https://python-all.ru/3.9/glossary.html#term-decorator). Выражения декоратора вычисляются при определении функции в области видимости, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращённое значение связывается с именем функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код295296```python297@f1(arg)298@f2299def func(): pass300```301302примерно эквивалентно303304```python305def func(): pass306func = f1(arg)(f2(func))307```308309за исключением того, что исходная функция не привязывается временно к имени `func`.310311Изменено в версии 3.9: Функции могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.9/reference/expressions.html#grammar-token-assignment-expression). Ранее грамматика была гораздо более строгой; подробности см. в [**PEP 614**](https://python-all.ru/3.9/reference/compound_stmts.html).312313Когда один или несколько [параметров](https://python-all.ru/3.9/glossary.html#term-parameter) имеют вид *параметр* `=` *выражение*, говорят, что функция имеет «значения параметров по умолчанию». Для параметра со значением по умолчанию соответствующий [аргумент](https://python-all.ru/3.9/glossary.html#term-argument) может быть опущен при вызове, и в этом случае подставляется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры до «`*`» также должны иметь значение по умолчанию – это синтаксическое ограничение, которое не отражено в грамматике.314315**Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции.** Это означает, что выражение вычисляется один раз, когда функция определяется, и одно и то же «предвычисленное» значение используется для каждого вызова. Это особенно важно понимать, когда параметр по умолчанию является изменяемым объектом, например списком или словарём: если функция изменяет объект (например, добавляет элемент в список), значение по умолчанию фактически изменяется. Обычно это не то, что предполагалось. Обойти это можно, используя `None` в качестве значения по умолчанию и явно проверяя его в теле функции, например:316317```python318def whats_on_the_telly(penguin=None):319 if penguin is None:320 penguin = []321 penguin.append("property of the zoo")322 return penguin323```324325Семантика вызова функций подробно описана в разделе [Calls](https://python-all.ru/3.9/reference/expressions.html#calls). Вызов функции всегда присваивает значения всем параметрам, указанным в списке параметров, либо из позиционных аргументов, либо из именованных аргументов, либо из значений по умолчанию. Если присутствует форма «`*identifier`», она инициализируется кортежем, принимающим все лишние позиционные параметры, по умолчанию пустой кортеж. Если присутствует форма «`**identifier`», она инициализируется новым упорядоченным отображением, принимающим все лишние именованные аргументы, по умолчанию новым пустым отображением того же типа. Параметры после «`*`» или «`*identifier`» являются параметрами только для ключевых слов и могут передаваться только именованными аргументами. Параметры до «`/`» являются параметрами только для позиции и могут передаваться только позиционными аргументами.326327Изменено в версии 3.8: Синтаксис параметра функции `/` может использоваться для обозначения позиционных параметров. Подробнее см. [**PEP 570**](https://python-all.ru/3.9/reference/compound_stmts.html).328329Параметры могут иметь [аннотацию](https://python-all.ru/3.9/glossary.html#term-function-annotation) вида «`: expression`» после имени параметра. Любой параметр может иметь аннотацию, даже параметры вида `*identifier` или `**identifier`. Функции могут иметь аннотацию возврата вида «`-> expression`» после списка параметров. Эти аннотации могут быть любым допустимым выражением Python. Наличие аннотаций не меняет семантику функции. Значения аннотаций доступны как значения словаря, ключами которого являются имена параметров, в атрибуте `__annotations__` объекта функции. Если используется импорт `annotations` из [`__future__`](https://python-all.ru/3.9/library/__future__.html#module-__future__), аннотации сохраняются в виде строк во время выполнения, что позволяет отложить их вычисление. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут вычисляться в порядке, отличном от порядка их появления в исходном коде.330331Также можно создавать анонимные функции (функции, не привязанные к имени) для немедленного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе [Lambdas](https://python-all.ru/3.9/reference/expressions.html#lambda). Обратите внимание, что лямбда-выражение – это всего лишь сокращение для упрощённого определения функции; функцию, определённую в инструкции «[`def`](https://python-all.ru/3.9/reference/compound_stmts.html#def)», можно передавать или присваивать другому имени так же, как функцию, определённую лямбда-выражением. Форма «`def`» на самом деле более мощная, поскольку позволяет выполнять несколько инструкций и аннотаций.332333**Замечание программисту:** Функции – объекты первого класса. Инструкция «`def`», выполненная внутри определения функции, определяет локальную функцию, которую можно вернуть или передать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробнее см. раздел [Naming and binding](https://python-all.ru/3.9/reference/executionmodel.html#naming).334335> **См. также**336>337> **[**PEP 3107**](https://python-all.ru/3.9/reference/compound_stmts.html) – Аннотации функций**338>339> Оригинальная спецификация аннотаций функций.340>341> **[**PEP 484**](https://python-all.ru/3.9/reference/compound_stmts.html) – Аннотации типов**342>343> Определение стандартного значения аннотаций: подсказки типов.344>345> **[**PEP 526**](https://python-all.ru/3.9/reference/compound_stmts.html) - Синтаксис аннотаций переменных**346>347> Возможность аннотировать типы объявлений переменных, включая переменные класса и переменные экземпляра348>349> **[**PEP 563**](https://python-all.ru/3.9/reference/compound_stmts.html) – Отложенное вычисление аннотаций**350>351> Поддержка прямых ссылок в аннотациях путём сохранения аннотаций в строковом виде во время выполнения вместо немедленного вычисления.352353## 8.7. Определения классов354355Определение класса создаёт объект класса (см. раздел [Стандартная иерархия типов](https://python-all.ru/3.9/reference/datamodel.html#types)):356357```358359classdef ::= [decorators] "class" classname [inheritance] ":" suite360inheritance ::= "(" [argument_list] ")"361classname ::= identifier362```363364Определение класса – это исполняемая инструкция. Список наследования обычно содержит список базовых классов (см. [Метаклассы](https://python-all.ru/3.9/reference/datamodel.html#metaclasses) для более продвинутого использования), поэтому каждый элемент списка должен вычисляться в объект класса, который допускает создание подклассов. Классы без списка наследования по умолчанию наследуют от базового класса [`object`](https://python-all.ru/3.9/library/functions.html#object); следовательно,365366```python367class Foo:368 pass369```370371эквивалентна372373```python374class Foo(object):375 pass376```377378Затем тело класса выполняется в новом фрейме выполнения (см. [Naming and binding](https://python-all.ru/3.9/reference/executionmodel.html#naming)), используя только что созданное локальное пространство имён и исходное глобальное пространство имён. (Обычно тело содержит в основном определения функций.) Когда выполнение тела класса завершается, его фрейм выполнения отбрасывается, но локальное пространство имён сохраняется. [3](https://python-all.ru/3.9/reference/compound_stmts.html#id6) Затем создаётся объект класса с использованием списка наследования для базовых классов и сохранённого локального пространства имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.379380Порядок, в котором атрибуты определяются в теле класса, сохраняется в `__dict__` нового класса. Обратите внимание, что это надёжно только сразу после создания класса и только для классов, определённых с использованием синтаксиса определения.381382Создание класса можно сильно настраивать с помощью [метаклассов](https://python-all.ru/3.9/reference/datamodel.html#metaclasses).383384Классы также могут быть декорированы: так же, как и при декорировании функций,385386```python387@f1(arg)388@f2389class Foo: pass390```391392примерно эквивалентно393394```python395class Foo: pass396Foo = f1(arg)(f2(Foo))397```398399Правила вычисления выражений декораторов такие же, как и для декораторов функций. Затем результат привязывается к имени класса.400401Изменено в версии 3.9: Классы могут быть декорированы любым допустимым [`assignment_expression`](https://python-all.ru/3.9/reference/expressions.html#grammar-token-assignment-expression). Ранее грамматика была гораздо более строгой; подробности см. в [**PEP 614**](https://python-all.ru/3.9/reference/compound_stmts.html).402403**Замечание для программиста:** Переменные, определённые в определении класса, являются атрибутами класса; они разделяются экземплярами. Атрибуты экземпляра можно задать в методе с помощью `self.name = value`. Как атрибуты класса, так и атрибуты экземпляра доступны через запись “`self.name`”, и при таком обращении атрибут экземпляра скрывает атрибут класса с тем же именем. Атрибуты класса могут использоваться как значения по умолчанию для атрибутов экземпляра, но использование изменяемых значений может привести к неожиданным результатам. [Дескрипторы](https://python-all.ru/3.9/reference/datamodel.html#descriptors) можно использовать для создания переменных экземпляра с другими деталями реализации.404405> **См. также**406>407> **[**PEP 3115**](https://python-all.ru/3.9/reference/compound_stmts.html) – Метаклассы в Python 3000**408>409> Предложение, изменившее объявление метаклассов на текущий синтаксис, и семантику того, как конструируются классы с метаклассами.410>411> **[**PEP 3129**](https://python-all.ru/3.9/reference/compound_stmts.html) - Декораторы классов**412>413> Предложение, добавившее декораторы классов. Декораторы функций и методов были введены в [**PEP 318**](https://python-all.ru/3.9/reference/compound_stmts.html).414415## 8.8. Корутины416417Новое в версии 3.5.418419### 8.8.1. Определение корутинной функции420421```422423async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"424 ["->" expression] ":" suite425```426427Выполнение корутин Python может приостанавливаться и возобновляться во многих точках (см. [корутина](https://python-all.ru/3.9/glossary.html#term-coroutine)). Внутри тела корутинной функции идентификаторы `await` и `async` становятся зарезервированными ключевыми словами; выражения [`await`](https://python-all.ru/3.9/reference/expressions.html#await), [`async for`](https://python-all.ru/3.9/reference/compound_stmts.html#async-for) и [`async with`](https://python-all.ru/3.9/reference/compound_stmts.html#async-with) могут использоваться только в телах корутинных функций.428429Функции, определённые с синтаксисом `async def`, всегда являются корутинными функциями, даже если они не содержат ключевых слов `await` или `async`.430431Использование выражения `yield from` в теле корутинной функции является [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError).432433Пример корутинной функции:434435```python436async def func(param1, param2):437 do_stuff()438 await some_coroutine()439```440441### 8.8.2. Инструкция `async for`442443```444445async_for_stmt ::= "async" for_stmt446```447448[Асинхронный итерируемый объект](https://python-all.ru/3.9/glossary.html#term-asynchronous-iterable) предоставляет метод `__aiter__`, который напрямую возвращает [асинхронный итератор](https://python-all.ru/3.9/glossary.html#term-asynchronous-iterator), способный вызывать асинхронный код в своём методе `__anext__`.449450Инструкция `async for` обеспечивает удобную итерацию по асинхронным итерируемым объектам.451452Следующий код:453454```python455async for TARGET in ITER:456 SUITE457else:458 SUITE2459```460461Семантически эквивалентен следующему:462463```python464iter = (ITER)465iter = type(iter).__aiter__(iter)466running = True467468while running:469 try:470 TARGET = await type(iter).__anext__(iter)471 except StopAsyncIteration:472 running = False473 else:474 SUITE475else:476 SUITE2477```478479См. также [`__aiter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__aiter__) и [`__anext__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__anext__) для подробностей.480481Использование инструкции `async for` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError).482483### 8.8.3. Инструкция `async with`484485```486487async_with_stmt ::= "async" with_stmt488```489490[Асинхронный менеджер контекста](https://python-all.ru/3.9/glossary.html#term-asynchronous-context-manager) – это [менеджер контекста](https://python-all.ru/3.9/glossary.html#term-context-manager), который может приостанавливать выполнение в своих методах *входа* и *выхода*.491492Следующий код:493494```python495async with EXPRESSION as TARGET:496 SUITE497```498499семантически эквивалентен следующему:500501```python502manager = (EXPRESSION)503aenter = type(manager).__aenter__504aexit = type(manager).__aexit__505value = await aenter(manager)506hit_except = False507508try:509 TARGET = value510 SUITE511except:512 hit_except = True513 if not await aexit(manager, *sys.exc_info()):514 raise515finally:516 if not hit_except:517 await aexit(manager, None, None, None)518```519520См. также [`__aenter__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__aenter__) и [`__aexit__()`](https://python-all.ru/3.9/reference/datamodel.html#object.__aexit__) для подробностей.521522Использование инструкции `async with` вне тела корутинной функции является [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError).523524> **См. также**525>526> **[**PEP 492**](https://python-all.ru/3.9/reference/compound_stmts.html) - Корутины с синтаксисом async и await**527>528> Предложение, которое сделало корутины полноценной самостоятельной концепцией в Python и добавило поддерживающий синтаксис.529530Сноски531532**[1](https://python-all.ru/3.9/reference/compound_stmts.html#id1)**533534Исключение распространяется по стеку вызовов, если только не встретится предложение [`finally`](https://python-all.ru/3.9/reference/compound_stmts.html#finally), которое в свою очередь возбуждает другое исключение. Это новое исключение приводит к потере старого.535536**[2](https://python-all.ru/3.9/reference/compound_stmts.html#id2)**537538Строковый литерал, появляющийся как первая инструкция в теле функции, преобразуется в атрибут `__doc__` функции и, следовательно, в [докстринг](https://python-all.ru/3.9/glossary.html#term-docstring) функции.539540**[3](https://python-all.ru/3.9/reference/compound_stmts.html#id3)**541542Строковый литерал, появляющийся в качестве первого оператора в теле класса, преобразуется в элемент `__doc__` пространства имён и, следовательно, в [докстринг](https://python-all.ru/3.9/glossary.html#term-docstring) класса.543