Spec-Zone.ru › Python 3.9

Составные операторы

Составные операторы содержат (группы) других операторов; они каким-либо образом влияют или управляют выполнением этих других операторов. Как правило, составные операторы занимают несколько строк, хотя в простых вариантах весь составной оператор может поместиться в одной строке.

Операторы 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() возвращает тройку, состоящую из класса исключения, экземпляра исключения и объекта трассировки (см. раздел Иерархия стандартных типов), идентифицирующего точку в программе, где произошло исключение. 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.

Когда оператор return, break или continue выполняется в блоке try оператора try…finally, блок finally также выполняется «по пути выхода».

Значение возврата функции определяется последним оператором return, который был выполнен. Поскольку блок finally всегда выполняется, оператор return , выполненный в блоке finally , всегда будет последним выполненным:

>>> def foo():
...     try:
...         return 'try'
...     finally:
...         return 'finally'
...
>>> foo()
'finally'

Дополнительную информацию об исключениях можно найти в разделе Исключения, а информацию об использовании оператора raise для генерации исключений можно найти в разделе Оператор raise.

Изменено в версии 3.8: До Python 3.8 оператор continue был недопустим в блоке finally из-за проблемы с реализацией.

8.5. The with оператор

Оператор with используется для обертывания выполнения блока методами, определёнными менеджером контекста (см. раздел Менеджеры контекста оператора With). Это позволяет упаковывать распространённые шаблоны try…except…finally для удобного повторного использования.

with_stmt ::=  "with" with_item ("," with_item)* ":" suite
with_item ::=  expression ["as" target]

Выполнение оператора with с одним «элементом» происходит следующим образом:

  1. Выражение контекста (выражение, указанное в with_item) вычисляется для получения менеджера контекста.
  2. Метод __enter__() менеджера контекста загружается для последующего использования.
  3. Метод __exit__() менеджера контекста загружается для последующего использования.
  4. Вызывается метод __enter__() менеджера контекста.
  5. Если в операторе with был указан целевой параметр, возвращаемое значение метода __enter__() присваивается ему.

    Примечание

    Оператор with гарантирует, что если метод __enter__() возвращает значение без ошибки, то метод __exit__() всегда будет вызван. Таким образом, если ошибка возникает во время присваивания в список целевых параметров, она обрабатывается так же, как ошибка в блоке.

  6. Выполняется блок кода.
  7. Вызывается метод __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: Поддержка нескольких выражений контекста.

См. также

PEP 343 - Оператор «with»

Спецификация, предыстория и примеры для оператора Python with.

8.6. Определения функций

Определение функции определяет объект пользовательской функции (см. раздел Иерархия стандартных типов):

funcdef                   ::=  [decorators] "def" funcname "(" [parameter_list] ")"
                               ["->" expression] ":" suite
decorators                ::=  decorator+
decorator                 ::=  "@" assignment_expression NEWLINE
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.

Изменено в версии 3.9: Функции могут быть декорированы любым допустимым assignment_expression. Ранее грамматика была гораздо более ограниченной; см. PEP 614 для получения подробностей.

Когда один или несколько параметров имеют вид параметр = выражение, функция имеет «значения параметров по умолчанию». Для параметра с значением по умолчанию соответствующий аргумент может быть опущен из вызова, в этом случае используется значение параметра по умолчанию. Если параметр имеет значение по умолчанию, все последующие параметры до «*» также должны иметь значение по умолчанию — это синтаксическое ограничение, которое не выражается в грамматике.

Значения параметров по умолчанию вычисляются слева направо при выполнении определения функции. Это означает, что выражение вычисляется один раз при определении функции, и это же «превычисленное» значение используется для каждого вызова. Это особенно важно учитывать, когда параметр по умолчанию является изменяемым объектом, например, списком или словарем: если функция изменяет объект (например, добавляет элемент в список), значение по умолчанию фактически изменяется. Это, как правило, не то, что предполагалось. Способ обойти это — использовать 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», выполненный внутри определения функции, определяет вложенную функцию, которую можно возвращать или передавать. Свободные переменные, используемые во вложенной функции, могут обращаться к локальным переменным содержащей её функции. Подробности см. в разделе Именование и привязка.

См. также

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 Затем создаётся объект класса, используя список наследования для базовых классов и сохранённое локальное пространство имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.

Порядок определения атрибутов в теле класса сохраняется в новом классе __dict__. Обратите внимание, что это надёжно только сразу после создания класса и только для классов, которые были определены с использованием синтаксиса определения.

Создание класса может быть существенно настраиваемым с помощью метаклассов.

Классы также могут быть декорированы: как и при декорировании функций,

@f1(arg)
@f2
class Foo: pass

приблизительно эквивалентно

class Foo: pass
Foo = f1(arg)(f2(Foo))

Правила оценки выражений декоратора такие же, как и для декораторов функций. Результат затем привязывается к имени класса.

Изменено в версии 3.9: Классы могут быть декорированы любым допустимым assignment_expression. Ранее грамматика была намного более ограниченной; см. PEP 614 для получения подробной информации.

Примечание для программиста: Переменные, определённые в определении класса, являются атрибутами класса; они используются экземплярами. Атрибуты экземпляра могут быть установлены в методе с помощью self.name = value. К атрибутам класса и экземпляра можно получить доступ через запись «self.name», и атрибут экземпляра скрывает атрибут класса с тем же именем при доступе таким образом. Атрибуты класса могут использоваться в качестве значений по умолчанию для атрибутов экземпляра, но использование изменяемых значений там может привести к неожиданным результатам. Дескрипторы могут быть использованы для создания переменных экземпляра с различными особенностями реализации.

См. также

PEP 3115 - Метаклассы в Python 3000

Предложение, изменившее объявление метаклассов на текущий синтаксис, и семантику построения классов с метаклассами.

PEP 3129 - Декораторы классов

Предложение, добавившее декораторы классов. Декораторы функций и методов были введены в PEP 318.

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

Асинхронно-итерируемый объект предоставляет метод __aiter__, который напрямую возвращает асинхронный итератор, который может вызывать асинхронный код в своём методе __anext__.

Инструкция 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)
aenter = type(manager).__aenter__
aexit = type(manager).__aexit__
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.9/reference/compound_stmts.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API