Составные операторы
Составные операторы содержат (группы) других операторов; они каким-либо образом влияют на или управляют выполнением этих других операторов. В общем случае составные операторы занимают несколько строк, хотя в простых случаях весь составной оператор может быть помещен в одну строку.
Операторы if, while и for реализуют традиционные конструкции управления потоком. Оператор try определяет обработчики исключений и/или код очистки для группы операторов, а оператор with позволяет выполнять код инициализации и завершения вокруг блока кода. Определения функций и классов также являются синтаксически составными операторами.
Составной оператор состоит из одного или нескольких «блоков». Блок состоит из заголовка и «тела». Заголовки блоков конкретного составного оператора находятся на одном и том же уровне отступа. Каждый заголовок блока начинается с уникального ключевого слова и заканчивается двоеточием. Тело — это группа операторов, управляемых блоком. Тело может содержать один или несколько операторов, разделенных точкой с запятой в одной строке с заголовком после двоеточия, или это может быть один или несколько отступов на последующих строках. Только последняя форма тела может содержать вложенные составные операторы; следующее не является допустимым, в основном потому, что не было бы ясно, к какому блоку if относится следующий блок else:
if test1: if test2: print(x)
Обратите также внимание, что точка с запятой связывает сильнее, чем двоеточие в этом контексте, поэтому в следующем примере либо все, либо ни один из вызовов print() не выполняется:
if x < y < z: print(x); print(y); print(z)
Подводя итог:
compound_stmt ::= if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| funcdef
| classdef
| async_with_stmt
| async_for_stmt
| async_funcdef
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Обратите внимание, что операторы всегда заканчиваются NEWLINE и, возможно, DEDENT. Также обратите внимание, что необязательные продолжения всегда начинаются с ключевого слова, которое не может начинать оператор, таким образом, нет никаких неоднозначностей («проблема с висящим else» решена в Python требованием отступать вложенные операторы if).
Форматирование правил грамматики в следующих разделах размещает каждый блок на отдельной строке для ясности.
8.1. Оператор if
Оператор if используется для условного выполнения:
if_stmt ::= "if" assignment_expression ":" suite
("elif" assignment_expression ":" suite)*
["else" ":" suite]
Он выбирает ровно один из блоков, вычисляя выражения по одному, пока не будет найдено истинное выражение (см. раздел Логические операции для определения истинности и ложности); затем выполняется этот блок (и никакая другая часть оператора if не выполняется или не вычисляется). Если все выражения ложны, выполняется блок блока else, если он присутствует.
8.2. Оператор while
Оператор while используется для многократного выполнения, пока выражение истинно:
while_stmt ::= "while" assignment_expression ":" suite
["else" ":" suite]
Это многократно проверяет выражение, и если оно истинно, выполняется первый блок; если выражение ложно (что может быть в первый раз, когда оно проверяется), выполняется блок блока else, если он присутствует, и цикл завершается.
Оператор break, выполненный в первом блоке, завершает цикл, не выполняя блок блока else. Оператор continue, выполненный в первом блоке, пропускает остальную часть блока и возвращается к проверке выражения.
8.3. Оператор for
Оператор for используется для итерации по элементам последовательности (например, строки, кортежа или списка) или другого итерируемого объекта:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
Список выражений вычисляется один раз; он должен возвращать итерируемый объект. Итератор создается для результата expression_list. Блок затем выполняется один раз для каждого элемента, предоставленного итератором, в порядке, возвращаемом итератором. Каждый элемент по очереди присваивается списку назначения по стандартным правилам присваивания (см. Операторы присваивания), а затем выполняется блок. Когда элементы исчерпаны (что происходит сразу, когда последовательность пуста или итератор вызывает исключение StopIteration), выполняется блок блока else, если он присутствует, и цикл завершается.
Оператор break, выполненный в первом блоке, завершает цикл, не выполняя блок блока else. Оператор continue, выполненный в первом блоке, пропускает остальную часть блока и переходит к следующему элементу или к блоку else, если следующего элемента нет.
Цикл for выполняет присваивание переменным в списке назначения. Это перезаписывает все предыдущие присваивания этим переменным, включая те, что были сделаны в блоке цикла for:
for i in range(10):
print(i)
i = 5 # this will not affect the for-loop
# because i will be overwritten with the next
# index in the range
Имена в списке назначения не удаляются по окончании цикла, но если последовательность пуста, они вообще не будут присвоены циклом. Подсказка: встроенная функция range() возвращает итератор целых чисел, подходящий для эмуляции эффекта паскальского for i := a to b do; например, list(range(3)) возвращает список [0, 1, 2].
Примечание
Существует тонкость, когда последовательность изменяется в цикле (это может произойти только для изменяемых последовательностей, например, списков). Внутренний счетчик используется для отслеживания того, какой элемент будет использован следующим, и он инкрементируется на каждой итерации. Когда этот счетчик достигнет длины последовательности, цикл завершается. Это означает, что если блок удаляет текущий (или предыдущий) элемент из последовательности, следующий элемент будет пропущен (поскольку он получает индекс текущего элемента, который уже был обработан). Аналогично, если блок вставляет элемент в последовательность перед текущим элементом, текущий элемент будет обработан снова при следующем проходе цикла. Это может привести к неприятным ошибкам, которых можно избежать, создав временную копию с помощью среза всей последовательности, например:
for x in a[:]:
if x < 0: a.remove(x)
8.4. Оператор try
Оператор try задаёт обработчики исключений и/или код очистки для группы операторов:
try_stmt ::= try1_stmt | try2_stmt
try1_stmt ::= "try" ":" suite
("except" [expression ["as" identifier]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
"finally" ":" suite
Оператор(ы) except задают один или более обработчиков исключений. Если в блоке try не происходит исключение, обработчик исключений не выполняется. Если исключение происходит в блоке try , начинается поиск обработчика исключения. Поиск выполняется по порядку для операторов except до тех пор, пока не будет найден обработчик, соответствующий этому исключению. Оператор except без выражения, если он присутствует, должен быть последним; он соответствует любому исключению. Для оператора except с выражением, это выражение оценивается, и оператор соответствует исключению, если полученный объект «совместим» с исключением. Объект совместим с исключением, если он является классом или базовым классом объекта исключения или кортежем, содержащим элемент, который является классом или базовым классом объекта исключения.
Если ни один оператор except не соответствует исключению, поиск обработчика исключения продолжается в окружающем коде и в стеке вызовов. 1
Если при вычислении выражения в заголовке оператора except возникает исключение, исходный поиск обработчика отменяется, и начинается поиск нового исключения в окружающем коде и в стеке вызовов (будто весь оператор try сгенерировал исключение).
Когда найден соответствующий оператор except, исключение присваивается цели, указанной после ключевого слова as в этом операторе except, если он присутствует, и выполняется блок оператора except. Все операторы except должны иметь исполняемый блок. Когда конец этого блока достигнут, выполнение продолжается нормально после всего оператора try. (Это означает, что если существуют два вложенных обработчика для одного и того же исключения, и исключение возникает в блоке try внутреннего обработчика, внешний обработчик не обработает исключение.)
Когда исключение было присвоено с помощью as target, оно очищается в конце оператора except. Это как будто
except E as N:
foo
было переведено на
except E as N:
try:
foo
finally:
del N
Это означает, что исключение нужно присвоить другому имени, чтобы иметь возможность обратиться к нему после оператора except. Исключения очищаются, потому что с отслеживанием, прикреплённым к ним, они образуют цикл ссылок с кадром стека, сохраняя все локальные переменные в этом кадре живыми до следующего сбора мусора.
Перед выполнением блока оператора except информация об исключении хранится в модуле sys и может быть получена через sys.exc_info(). sys.exc_info() возвращает кортеж из 3 элементов: класс исключения, экземпляр исключения и объект отслеживания (см. раздел Стандартная иерархия типов), идентифицирующий точку в программе, где возникло исключение. Значения sys.exc_info() восстанавливаются до своих предыдущих значений (до вызова) при возвращении из функции, которая обрабатывала исключение.
Необязательный оператор else выполняется, если поток управления выходит из блока try, исключение не было поднято и не выполнялся оператор return, continue или break. Исключения в блоке else не обрабатываются предыдущими операторами except.
Если оператор finally присутствует, он задаёт обработчик «очистки». Блок try выполняется, включая операторы except и else . Если в одном из блоков возникает исключение и оно не обрабатывается, исключение временно сохраняется. Выполняется блок оператора finally. Если сохранено исключение, оно повторно поднимается в конце блока finally. Если блок finally вызывает другое исключение, сохранённое исключение устанавливается как контекст нового исключения. Если блок finally выполняет оператор return, break или continue, сохранённое исключение отбрасывается:
>>> def f(): ... try: ... 1/0 ... finally: ... return 42 ... >>> f() 42
Информация об исключении недоступна программе во время выполнения оператора finally.
Когда в блоке try оператора try…finally выполняется оператор return, break или continue, также выполняется блок оператора finally «по пути выхода».
Возвращаемое значение функции определяется последним оператором return, выполненным. Так как блок finally всегда выполняется, оператор return , выполненный в блоке finally , всегда будет последним выполненным:
>>> def foo(): ... try: ... return 'try' ... finally: ... return 'finally' ... >>> foo() 'finally'
Дополнительную информацию об исключениях можно найти в разделе Исключения, а информацию об использовании оператора raise для генерации исключений можно найти в разделе Оператор raise.
8.5. The with оператор
Оператор with используется для обертывания выполнения блока методами, определенными менеджером контекста (см. раздел Менеджеры контекста оператора With). Это позволяет обобщить распространённые шаблоны try…except…finally для удобного повторного использования.
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
Выполнение оператора with с одним «элементом» происходит следующим образом:
- Выражение контекста (выражение, заданное в
with_item) вычисляется для получения менеджера контекста. - Загружается метод менеджера контекста
__enter__()для последующего использования. - Загружается метод менеджера контекста
__exit__()для последующего использования. - Вызывается метод
__enter__()менеджера контекста. -
Если в операторе
withбыл указан целевой параметр, возвращаемое значение от__enter__()присваивается ему.Примечание
Оператор
withгарантирует, что если метод__enter__()возвращает значение без ошибки, то__exit__()всегда будет вызван. Таким образом, если ошибка произошла во время присваивания целевому списку, она будет обработана так же, как и ошибка, произошедшая в блоке. См. шаг 6 ниже. - Выполняется блок кода.
-
Вызывается метод
__exit__()менеджера контекста. Если выполнение блока прервалось из-за исключения, тип, значение и трассировка исключения передаются в качестве аргументов методу__exit__(). В противном случае передаются три аргументаNone.Если выполнение блока прервалось из-за исключения, и возвращаемое значение от метода
__exit__()было ложным, исключение повторно поднимается. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается со следующим оператором после оператораwith.Если выполнение блока прервалось по любой причине, кроме исключения, возвращаемое значение от
__exit__()игнорируется, и выполнение продолжается в обычном месте для данного типа завершения.
Следующий код:
with EXPRESSION as TARGET:
SUITE
семантически эквивалентен:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
При использовании нескольких элементов, менеджеры контекстов обрабатываются так, как будто вложены несколько операторов with:
with A() as a, B() as b:
SUITE
семантически эквивалентен:
with A() as a:
with B() as b:
SUITE
Изменено в версии 3.1: Поддержка нескольких выражений контекста.
8.6. Определения функций
Определение функции определяет объект пользовательской функции (см. раздел Иерархия стандартных типов):
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
dotted_name ::= identifier ("." identifier)*
parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
| parameter_list_no_posonly
parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
| parameter_list_starargs
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
| "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier
Определение функции — это исполняемая инструкция. Его выполнение связывает имя функции в текущем локальном пространстве имен с объектом функции (оболочкой вокруг исполняемого кода функции). Этот объект функции содержит ссылку на текущее глобальное пространство имен как на глобальное пространство имен, которое будет использоваться при вызове функции.
Определение функции не выполняет тело функции; это выполняется только при вызове функции. 2
Определение функции может быть заключено в одну или несколько выражений декоратора. Выражения декораторов вычисляются при определении функции в области, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращаемое значение связывается с именем функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код
@f1(arg) @f2 def func(): pass
примерно эквивалентен
def func(): pass func = f1(arg)(f2(func))
за исключением того, что исходная функция временно не связывается с именем func.
Когда один или несколько параметров имеют вид параметр = выражение, функция имеет «значения параметров по умолчанию». Для параметра с значением по умолчанию соответствующий аргумент может быть опущен из вызова, в этом случае используется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры до «*» также должны иметь значение по умолчанию — это синтаксическое ограничение, которое не выражено в грамматике.
Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции. Это означает, что выражение вычисляется один раз при определении функции, и то же «предвычисленное» значение используется для каждого вызова. Это особенно важно понимать, когда параметр по умолчанию является изменяемым объектом, таким как список или словарь: если функция изменяет объект (например, добавляет элемент в список), значение по умолчанию фактически изменяется. Как правило, это не то, что предполагалось. Способ обойти это — использовать None в качестве значения по умолчанию и явно проверять его в теле функции, например:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
Семантика вызова функции более подробно описана в разделе Вызовы. Вызов функции всегда присваивает значения всем параметрам, указанным в списке параметров, либо из позиционных аргументов, либо из ключевых аргументов, либо из значений по умолчанию. Если присутствует форма «*identifier», она инициализируется кортежем, получающим любые избыточные позиционные параметры, по умолчанию — пустой кортеж. Если присутствует форма «**identifier», она инициализируется новым упорядоченным отображением, получающим любые избыточные ключевые аргументы, по умолчанию — новое пустое отображение того же типа. Параметры после «*» или «*identifier» являются ключевыми параметрами только по ключевым аргументам. Параметры до «/» являются позиционными параметрами только по позиционным аргументам.
Изменено в версии 3.8: Синтаксис параметра функции / может использоваться для указания позиционных параметров только по позиции. Подробности см. в PEP 570.
Параметры могут иметь аннотацию вида «: expression» после имени параметра. Любой параметр может иметь аннотацию, даже те, которые имеют вид *identifier или **identifier. Функции могут иметь аннотацию «возврат» вида «-> expression» после списка параметров. Эти аннотации могут быть любыми допустимыми выражениями Python. Наличие аннотаций не изменяет семантики функции. Значения аннотаций доступны как значения словаря, ключи которого — имена параметров, в атрибуте __annotations__ объекта функции. Если импорт annotations из __future__ используется, аннотации сохраняются в виде строк во время выполнения, что позволяет отложить вычисление. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут вычисляться в другом порядке, чем в исходном коде.
Также возможно создание анонимных функций (функций, не связанных с именем) для непосредственного использования в выражениях. Это использует лямбда-выражения, описанные в разделе Лямбда-выражения. Обратите внимание, что лямбда-выражение — это просто сокращенная запись для упрощенного определения функции; функция, определенная в инструкции «def», может быть передана или назначена другому имени так же, как функция, определенная лямбда-выражением. Форма «def» на самом деле более мощная, поскольку она позволяет выполнить несколько операторов и аннотаций.
Примечание программисту: Функции — это объекты первого класса. Инструкция «def», выполненная внутри определения функции, определяет локальную функцию, которую можно возвращать или передавать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробности см. в разделе Именование и привязка.
См. также
- PEP 3107 - Аннотации функций
-
Исходная спецификация для аннотаций функций.
- PEP 484 - Типы подсказок
-
Определение стандартного значения для аннотаций: подсказки типов.
- PEP 526 - Синтаксис аннотаций переменных
-
Возможность подсказки типов для объявлений переменных, включая переменные класса и экземпляра.
- PEP 563 - Отложенное вычисление аннотаций
-
Поддержка ссылок вперед в аннотациях путем сохранения аннотаций в строчном формате во время выполнения вместо немедленного вычисления.
8.7. Определения классов
Определение класса создаёт объект класса (см. раздел Иерархия стандартных типов):
classdef ::= [decorators] "class" classname [inheritance] ":" suite
inheritance ::= "(" [argument_list] ")"
classname ::= identifier
Определение класса является выполняемой инструкцией. Список наследования обычно содержит список базовых классов (см. Метаклассы для более продвинутых случаев использования), поэтому каждый элемент списка должен вычисляться в объект класса, который допускает создание подклассов. Классы без списка наследования по умолчанию наследуют от базового класса object; следовательно,
class Foo:
pass
эквивалентно
class Foo(object):
pass
Затем тело класса выполняется в новой фрейме выполнения (см. Имена и привязки), используя новое локальное пространство имён и исходное глобальное пространство имён. (Обычно тело содержит в основном определения функций.) После завершения выполнения тела класса его фрейм выполнения удаляется, но его локальное пространство имён сохраняется. 3 Затем создаётся объект класса, используя список наследования базовых классов и сохранённое локальное пространство имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.
Порядок определения атрибутов в теле класса сохраняется в новом словаре атрибутов класса. Обратите внимание, что это надежно только сразу после создания класса и только для классов, определённых с помощью синтаксиса определения.
Создание класса можно сильно настроить, используя метаклассы.
Классы также могут быть декорированы: так же, как при декорировании функций,
@f1(arg) @f2 class Foo: pass
примерно эквивалентно
class Foo: pass Foo = f1(arg)(f2(Foo))
Правила вычисления выражений декораторов такие же, как для декораторов функций. Результат затем привязывается к имени класса.
Примечание для программиста: Переменные, определённые в определении класса, являются атрибутами класса; они общие для экземпляров. Атрибуты экземпляров можно устанавливать в методе с помощью self.name = value. И атрибуты класса, и атрибуты экземпляров доступны через обозначение «self.name», и атрибут экземпляра скрывает атрибут класса с тем же именем при обращении таким образом. Атрибуты класса можно использовать в качестве значений по умолчанию для атрибутов экземпляров, но использование изменяемых значений может привести к неожиданным результатам. Дескрипторы можно использовать для создания переменных экземпляров с различными деталями реализации.
8.8. Корутины
Новое в версии 3.5.
8.8.1. Определение функции-корутины
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
Выполнение Python-корутин может приостанавливаться и возобновляться во многих точках (см. корутину). Внутри тела функции-корутины await и async идентификаторы становятся зарезервированными ключевыми словами; await выражения, async for и async with могут использоваться только в телах функций-корутин.
Функции, определённые с помощью синтаксиса async def, всегда являются функциями-корутинами, даже если они не содержат await или async ключевых слов.
Использование yield from выражения внутри тела функции-корутины является SyntaxError.
Пример функции-корутины:
async def func(param1, param2):
do_stuff()
await some_coroutine()
8.8.2. Инструкция async for
async_for_stmt ::= "async" for_stmt
Асинхронный итератор способен вызывать асинхронный код в своём методе iter, а асинхронный итератор может вызывать асинхронный код в своём методе next.
Инструкция async for позволяет удобно итерировать по асинхронным итераторам.
Следующий код:
async for TARGET in ITER:
SUITE
else:
SUITE2
Семантически эквивалентен:
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True
while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
См. также __aiter__() и __anext__() для получения подробностей.
Использование инструкции async for вне тела функции-корутины является SyntaxError.
8.8.3. Инструкция async with
async_with_stmt ::= "async" with_stmt
Асинхронный менеджер контекста — это менеджер контекста, способный приостанавливать выполнение в методах enter и exit.
Следующий код:
async with EXPRESSION as TARGET:
SUITE
семантически эквивалентен:
manager = (EXPRESSION)
aexit = type(manager).__aexit__
aenter = type(manager).__aenter__
value = await aenter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(manager, None, None, None)
См. также __aenter__() и __aexit__() для получения подробностей.
Использование инструкции async with вне тела функции-корутины является SyntaxError.
См. также
- PEP 492 - Корутины с синтаксисом async и await
-
Предложение, которое сделало корутины полноценной самостоятельной концепцией в Python и добавило поддерживающий синтаксис.
Примечания
-
1 -
Исключение распространяется по стеку вызова, если нет
finallyблока, который случается поднять другое исключение. Это новое исключение приводит к потере старого. -
2 -
Строковая литерал, появляющаяся в качестве первой инструкции в теле функции, преобразуется в атрибут документации функции и, следовательно, в строку документации функции.
-
3 -
Строковая литерал, появляющаяся в качестве первой инструкции в теле класса, преобразуется в элемент пространства имён и, следовательно, в строку документации класса.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/reference/compound_stmts.html