Содержание страницы
8. Составные инструкции¶Compound statements
Составные инструкции содержат (группы) других инструкций; они влияют на выполнение этих других инструкций или управляют им. В общем случае составные инструкции охватывают несколько строк, хотя в простых вариантах вся составная инструкция может помещаться в одну строку.
Инструкции 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_funcdefsuite ::=stmt_listNEWLINE | NEWLINE INDENTstatement+ DEDENT statement ::=stmt_listNEWLINE |compound_stmtstmt_list ::=simple_stmt(";"simple_stmt)* [";"]
Обратите внимание, что инструкции всегда заканчиваются NEWLINE, за которым может следовать
DEDENT. Также обратите внимание, что опциональные продолжения всегда начинаются с
ключевого слова, которое не может начинать инструкцию, поэтому неоднозначностей нет (проблема
«висячего else» решается в Python требованием, чтобы вложенные
инструкции if имели отступ).
Форматирование грамматических правил в следующих разделах помещает каждое предложение на отдельную строку для ясности.
8.1. Инструкция if¶The if statement
Инструкция if используется для условного выполнения:
if_stmt ::= "if"expression":"suite("elif"expression":"suite)* ["else" ":"suite]
Он выбирает ровно один из наборов инструкций, вычисляя выражения одно за другим,
пока одно из них не окажется истинным (см. раздел Булевы операции для определения
истины и лжи); затем этот набор выполняется (и никакая другая часть инструкции
if не выполняется и не вычисляется). Если все выражения
ложны, выполняется набор инструкций предложения else, если оно присутствует.
8.2. Инструкция while¶The while statement
Инструкция while используется для повторного выполнения, пока
выражение истинно:
while_stmt ::= "while"expression":"suite["else" ":"suite]
Эта инструкция многократно проверяет выражение и, если оно истинно, выполняет первый
набор инструкций; если выражение ложно (возможно, при первой проверке), то
набор инструкций предложения else, если оно присутствует, выполняется, и цикл
завершается.
Инструкция break, выполненная в первом наборе, завершает цикл,
не выполняя набор инструкций предложения else. Инструкция continue,
выполненная в первом наборе, пропускает оставшуюся часть набора и возвращается
к проверке выражения.
8.3. Инструкция for¶The for statement
Инструкция 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 # это не повлияет на цикл for
# потому что i будет перезаписано следующим
# индексом в range
Имена в списке целей не удаляются по завершении цикла, но если последовательность пуста, они вообще не будут присвоены циклом. Подсказка: встроенная функция range() возвращает итератор целых чисел, подходящий для имитации эффекта for i := a to b do в Pascal; например, list(range(3)) возвращает список [0, 1, 2].
Примечание
Существует тонкость, когда последовательность изменяется циклом (это возможно только для изменяемых последовательностей, например списков). Внутренний счётчик используется для отслеживания того, какой элемент будет обработан следующим, и он увеличивается на каждой итерации. Когда этот счётчик достигает длины последовательности, цикл завершается. Это означает, что если блок удаляет текущий (или предыдущий) элемент из последовательности, следующий элемент будет пропущен (поскольку он получает индекс текущего элемента, который уже был обработан). Аналогично, если блок вставляет элемент в последовательность перед текущим, текущий элемент будет обработан снова при следующем проходе цикла. Это может привести к неприятным ошибкам, которых можно избежать, создав временную копию с помощью среза всей последовательности, например,
for x in a[:]:
if x < 0: a.remove(x)
8.4. Инструкция try¶The try statement
Инструкция try задаёт обработчики исключений и/или код очистки
для группы инструкций:
try_stmt ::=try1_stmt|try2_stmttry1_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() возвращает кортеж из трёх элементов: класс исключения, экземпляр исключения и объект трассировки (см. раздел Стандартная иерархия типов), указывающий точку программы, где произошло исключение. Значения sys.exc_info() восстанавливаются до предыдущих (до вызова) при возврате из функции, обработавшей исключение.
Необязательное предложение else выполняется, если поток управления покидает блок try, не было вызвано исключение и не выполнялся оператор return, continue или break. Исключения в предложении else не обрабатываются предшествующими предложениями except.
Если присутствует finally, он задаёт обработчик «очистки». Выполняется предложение try, включая любые предложения except и else. Если в любом из предложений возникает исключение и оно не обрабатывается, исключение временно сохраняется. Выполняется предложение finally. Если есть сохранённое исключение, оно повторно возбуждается в конце предложения finally. Если предложение finally возбуждает другое исключение, сохранённое исключение становится контекстом нового исключения. Если предложение finally выполняет оператор return или break, сохранённое исключение отбрасывается:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
Информация об исключении недоступна программе во время выполнения предложения finally.
Когда оператор return, break или continue выполняется в блоке try оператора try…finally, предложение finally также выполняется «по выходу». Оператор continue недопустим в предложении finally. (Причина – проблема текущей реализации; это ограничение может быть снято в будущем).
Возвращаемое значение функции определяется последней выполненной инструкцией return.
Поскольку предложение finally выполняется всегда, инструкция
return, выполненная в предложении finally, всегда будет последней выполненной:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
Дополнительную информацию об исключениях можно найти в разделе Исключения,
а информация об использовании инструкции raise для генерации исключений
приведена в разделе Инструкция raise.
8.5. Инструкция with¶The with statement
Оператор with используется для обёртывания выполнения блока методами, определёнными контекстным менеджером (см. раздел Контекстные менеджеры оператора with). Это позволяет инкапсулировать типичные шаблоны использования try…except…finally для удобного повторного использования.
with_stmt ::= "with"with_item(","with_item)* ":"suitewith_item ::=expression["as"target]
Выполнение оператора with с одним «элементом» происходит следующим образом:
Контекстное выражение (выражение, указанное в
with_item) вычисляется для получения менеджера контекста.Метод
__exit__()контекстного менеджера загружается для последующего использования.Метод
__enter__()контекстного менеджера вызывается.Если в операторе
withбыла указана цель, возвращаемое значение из__enter__()присваивается ей.Примечание
Инструкция
withгарантирует, что если метод__enter__()завершится без ошибки, то__exit__()будет вызван обязательно. Таким образом, если во время присваивания списку целей произойдет ошибка, она будет обработана так же, как ошибка, возникшая внутри блока. См. шаг 6 ниже.Выполняется блок.
Вызывается метод
__exit__()менеджера контекста. Если исключение вызвало выход из блока, его тип, значение и traceback передаются в качестве аргументов__exit__(). В противном случае передаются три аргументаNone.Если блок был завершён из-за исключения и возвращаемое значение метода
__exit__()было ложным, исключение возбуждается повторно. Если возвращаемое значение было истинным, исключение подавляется, и выполнение продолжается с оператора, следующего за операторомwith.Если блок был завершён по любой причине, кроме исключения, возвращаемое значение
__exit__()игнорируется, и выполнение продолжается в обычном месте для данного типа завершения.
При наличии нескольких элементов менеджеры контекста обрабатываются так, как если бы несколько
операторов with были вложены:
with A() as a, B() as b:
suite
эквивалентна
with A() as a:
with B() as b:
suite
Изменено в версии 3.1: Поддержка нескольких выражений контекста.
8.6. Определения функций¶Function definitions
Определение функции создаёт объект пользовательской функции (см. раздел Стандартная иерархия типов):
funcdef ::= [decorators] "def"funcname"(" [parameter_list] ")" ["->"expression] ":"suitedecorators ::=decorator+ decorator ::= "@"dotted_name["(" [argument_list[","]] ")"] NEWLINE dotted_name ::=identifier("."identifier)* parameter_list ::=defparameter(","defparameter)* ["," [parameter_list_starargs]] |parameter_list_starargsparameter_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» являются параметрами только по ключу и могут передаваться только с помощью именованных аргументов.
Параметры могут иметь аннотации вида ": expression" после имени параметра. Любой параметр может иметь аннотацию, даже такие, как *identifier или **identifier. Функции могут иметь аннотацию "return" вида "-> expression" после списка параметров. Эти аннотации могут быть любым допустимым выражением Python и вычисляются при выполнении определения функции. Аннотации могут вычисляться в порядке, отличном от того, в котором они встречаются в исходном коде. Наличие аннотаций не меняет семантику функции. Значения аннотаций доступны как значения словаря, индексированного по именам параметров, в атрибуте __annotations__ объекта функции.
Также можно создавать анонимные функции (функции, не привязанные к имени) для немедленного использования в выражениях. Для этого используются лямбда-выражения, описанные в разделе Lambdas. Обратите внимание, что лямбда-выражение – это всего лишь сокращение для упрощённого определения функции; функцию, определённую в инструкции «def», можно передавать или присваивать другому имени так же, как функцию, определённую лямбда-выражением. Форма «def» на самом деле более мощная, поскольку позволяет выполнять несколько инструкций и аннотаций.
Замечание программисту: Функции – объекты первого класса. Инструкция «def», выполненная внутри определения функции, определяет локальную функцию, которую можно вернуть или передать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным функции, содержащей def. Подробнее см. раздел Naming and binding.
См. также
- PEP 3107 – Аннотации функций
Оригинальная спецификация аннотаций функций.
8.7. Определения классов¶Class definitions
Определение класса создаёт объект класса (см. раздел Стандартная иерархия типов):
classdef ::= [decorators] "class"classname[inheritance] ":"suiteinheritance ::= "(" [argument_list] ")" classname ::=identifier
Определение класса – это исполняемая инструкция. Список наследования обычно содержит список базовых классов (см. Метаклассы для более продвинутого использования), поэтому каждый элемент списка должен вычисляться в объект класса, который допускает создание подклассов. Классы без списка наследования по умолчанию наследуют от базового класса object; следовательно,
class Foo:
pass
эквивалентна
class Foo(object):
pass
Затем тело класса выполняется в новом фрейме выполнения (см. Naming and binding), используя только что созданное локальное пространство имён и исходное глобальное пространство имён. (Обычно тело содержит в основном определения функций.) Когда выполнение тела класса завершается, его фрейм выполнения отбрасывается, но локальное пространство имён сохраняется. 3 Затем создаётся объект класса с использованием списка наследования для базовых классов и сохранённого локального пространства имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.
Порядок, в котором атрибуты определяются в теле класса, сохраняется в __dict__ нового класса. Обратите внимание, что это надёжно только сразу после создания класса и только для классов, определённых с использованием синтаксиса определения.
Создание класса можно сильно настраивать с помощью метаклассов.
Классы также могут быть декорированы: так же, как и при декорировании функций,
@f1(arg)
@f2
class Foo: pass
примерно эквивалентно
class Foo: pass
Foo = f1(arg)(f2(Foo))
Правила вычисления выражений декораторов такие же, как и для декораторов функций. Затем результат привязывается к имени класса.
Замечание для программиста: Переменные, определённые в определении класса, являются атрибутами класса;
они разделяются экземплярами. Атрибуты экземпляра можно задать в методе с помощью self.name = value. Как атрибуты класса, так и атрибуты экземпляра
доступны через запись “self.name”, и при таком обращении атрибут экземпляра скрывает
атрибут класса с тем же именем. Атрибуты класса могут использоваться как значения по умолчанию для атрибутов экземпляра, но использование изменяемых
значений может привести к неожиданным результатам. Дескрипторы
можно использовать для создания переменных экземпляра с другими деталями реализации.
8.8. Корутины¶Coroutines
Новое в версии 3.5.
8.8.1. Определение корутинной функции¶Coroutine function definition
async_funcdef ::= [decorators] "async" "def"funcname"(" [parameter_list] ")" ["->"expression] ":"suite
Выполнение корутин Python может приостанавливаться и возобновляться во многих точках (см. корутина). В теле корутины идентификаторы await и async становятся зарезервированными ключевыми словами; выражения await, async for и async with могут использоваться только в телах корутин.
Функции, определённые с синтаксисом async def, всегда являются корутинными функциями,
даже если они не содержат ключевых слов await или async.
Использование выражений yield from в async def корутинах является SyntaxError.
Пример корутинной функции:
async def func(param1, param2):
do_stuff()
await some_coroutine()
8.8.2. Инструкция async for¶The async for statement
async_for_stmt ::= "async" for_stmt
Асинхронный итерируемый объект способен вызывать асинхронный код в своей реализации iter, а асинхронный итератор может вызывать асинхронный код в своём методе next.
Оператор async for позволяет удобно выполнять итерацию по асинхронным итераторам.
Следующий код:
async for TARGET in ITER:
BLOCK
else:
BLOCK2
Семантически эквивалентен следующему:
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True
while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
BLOCK
else:
BLOCK2
См. также __aiter__() и __anext__() для подробностей.
Использование оператора async for вне async def функции является SyntaxError.
8.8.3. Инструкция async with¶The async with statement
async_with_stmt ::= "async" with_stmt
Асинхронный менеджер контекста – это менеджер контекста, который может приостанавливать выполнение в своих методах входа и выхода.
Следующий код:
async with EXPR as VAR:
BLOCK
Семантически эквивалентен следующему:
mgr = (EXPR)
aexit = type(mgr).__aexit__
aenter = type(mgr).__aenter__(mgr)
VAR = await aenter
try:
BLOCK
except:
if not await aexit(mgr, *sys.exc_info()):
raise
else:
await aexit(mgr, None, None, None)
См. также __aenter__() и __aexit__() для подробностей.
Использование оператора async with вне async def функции является SyntaxError.
См. также
- PEP 492 - Корутины с синтаксисом async и await
Предложение, которое сделало корутины полноценной самостоятельной концепцией в Python и добавило поддерживающий синтаксис.
Сноски
- 1
Исключение распространяется по стеку вызовов, если только не встретится предложение
finally, которое в свою очередь возбуждает другое исключение. Это новое исключение приводит к потере старого.- 2
Строковый литерал, появляющийся как первая инструкция в теле функции, преобразуется в атрибут
__doc__функции и, следовательно, в докстринг функции.- 3
Строковый литерал, появляющийся в качестве первого оператора в теле класса, преобразуется в элемент
__doc__пространства имён и, следовательно, в докстринг класса.