Spec-Zone.ru › Python 3.10

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

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

Операторы 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
                   | match_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() представляет неизменяемые арифметические последовательности целых чисел. Например, при итерации range(3) последовательно получаются 0, 1 и 2.

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(), восстанавливаются до их предыдущих значений при выходе из обработчика исключений:

>>> print(sys.exc_info())
(None, None, None)
>>> try:
...     raise TypeError
... except:
...     print(sys.exc_info())
...     try:
...          raise ValueError
...     except:
...         print(sys.exc_info())
...     print(sys.exc_info())
...
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
(<class 'ValueError'>, ValueError(), <traceback object at 0x10efad040>)
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
>>> print(sys.exc_info())
(None, None, None)

Необязательный оператор 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.

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

8.5. Оператор with

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

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

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

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

    Примечание

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

  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

Также можно писать менеджеры контекста с несколькими элементами на нескольких строках, если элементы заключены в скобки. Например:

with (
    A() as a,
    B() as b,
):
    SUITE

Изменено в версии 3.1: Поддержка нескольких выражений контекста.

Изменено в версии 3.10: Поддержка использования группирующих скобок для разбиения оператора на несколько строк.

См. также

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

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

8.6. Оператор match

Новое в версии 3.10.

Оператор match используется для сопоставления шаблонов. Синтаксис:

match_stmt   ::=  'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
subject_expr ::=  star_named_expression "," star_named_expressions?
                  | named_expression
case_block   ::=  'case' patterns [guard] ":" block

Примечание

В этом разделе одинарные кавычки используются для обозначения мягких ключевых слов.

Сопоставление шаблонов принимает шаблон в качестве входных данных (после case) и значение субъекта (после match). Шаблон (который может содержать подшаблоны) сопоставляется со значением субъекта. Результаты:

  • Успешное или неудачное сопоставление (также называемое успехом или неудачей шаблона).
  • Возможная привязка сопоставленных значений к имени. Предварительные условия для этого описаны ниже.

Ключевые слова match и case являются мягкими ключевыми словами.

См. также

  • PEP 634 – Спецификация структурного сопоставления шаблонов
  • PEP 636 – Руководство по структурному сопоставлению шаблонов

8.6.1. Обзор

Вот обзор логического потока оператора match:

  1. Вычисляется выражение субъекта subject_expr и получаем значение субъекта. Если выражение субъекта содержит запятую, создается кортеж, используя стандартные правила.
  2. Каждый шаблон в операторе case_block пытается сопоставиться со значением субъекта. Специфические правила успеха или неудачи описаны ниже. Попытка сопоставления также может привязать некоторые или все автономные имена в шаблоне. Точные правила привязки шаблонов отличаются в зависимости от типа шаблона и указаны ниже. Привязки имен, выполненные во время успешного сопоставления шаблона, сохраняются после выполнения блока и могут использоваться после оператора match.

    Примечание

    Во время неудачных сопоставлений шаблонов некоторые подшаблоны могут быть успешными. Не полагайтесь на то, что при неудачном сопоставлении будут созданы привязки. И наоборот, не полагайтесь на то, что переменные останутся неизменными после неудачного сопоставления. Точное поведение зависит от реализации и может изменяться. Это преднамеренное решение, позволяющее различным реализациям добавлять оптимизации.

  3. Если шаблон сопоставлен, вычисляется соответствующее условие (если оно есть). В этом случае все привязки имен гарантированно уже выполнены.

    • Если условие вычисляет как истинное или отсутствует, выполняется блок кода block внутри оператора case_block.
    • В противном случае проверяется следующий шаблон, как описано выше.
    • Если нет других блоков case, оператор match завершается.

Примечание

Пользователи обычно не должны полагаться на оценку шаблонов. В зависимости от реализации интерпретатор может кэшировать значения или использовать другие оптимизации, которые пропускают повторные оценки.

Пример оператора match:

>>> flag = False
>>> match (100, 200):
...    case (100, 300):  # Mismatch: 200 != 300
...        print('Case 1')
...    case (100, 200) if flag:  # Successful match, but guard fails
...        print('Case 2')
...    case (100, y):  # Matches and binds y to 200
...        print(f'Case 3, y: {y}')
...    case _:  # Pattern not attempted
...        print('Case 4, I match anything!')
...
Case 3, y: 200

В этом случае if flag является условием. Подробнее об этом в следующем разделе.

8.6.2. Условия

guard ::=  "if" named_expression

Условие (являющееся частью case) должно быть истинным, чтобы код внутри блока case выполнился. Оно имеет вид: if, за которым следует выражение.

Логический поток блока case с условием guard следующий:

  1. Проверка, что шаблон в блоке case успешно сопоставлен. Если шаблон не сопоставлен, условие guard не вычисляется, и проверяется следующий блок case.
  2. Если шаблон сопоставлен, вычисляется условие guard.

    • Если условие guard истинно, блок case выбирается.
    • Если условие guard ложно, блок case не выбирается.
    • Если при вычислении условия guard возникает исключение, оно перебрасывается.

Условия могут иметь побочные эффекты, так как они являются выражениями. Вычисление условий должно выполняться от первого к последнему блоку case, по одному за раз, пропуская блоки case, шаблоны которых не совпадают. (То есть вычисление условий должно происходить в порядке.) Вычисление условий должно прекратиться, как только блок case будет выбран.

8.6.3. Неопровержимые блоки case

Неопровержимый блок case — это блок case, который сопоставляется со всем. В операторе match может быть не более одного неопровержимого блока case, и он должен быть последним.

Блок case считается неопровержимым, если у него нет условия и его шаблон неопровержим. Шаблон считается неопровержимым, если по его синтаксису можно доказать, что он всегда будет сопоставлен. Только следующие шаблоны являются неопровержимыми:

  • Шаблоны AS, левая часть которых неопровержима
  • Шаблоны OR, содержащие по крайней мере один неопровержимый шаблон
  • Шаблоны захвата
  • Шаблоны подстановок
  • скобочные неопровержимые шаблоны

8.6.4. Шаблоны

Примечание

В этом разделе используются обозначения грамматики, выходящие за рамки стандартного EBNF:

  • обозначение SEP.RULE+ является сокращением для RULE (SEP RULE)*
  • обозначение !RULE является сокращением для утверждения отрицательного предвосхищения

Синтаксис верхнего уровня для patterns:

patterns       ::=  open_sequence_pattern | pattern
pattern        ::=  as_pattern | or_pattern
closed_pattern ::=  | literal_pattern
                    | capture_pattern
                    | wildcard_pattern
                    | value_pattern
                    | group_pattern
                    | sequence_pattern
                    | mapping_pattern
                    | class_pattern

В описаниях ниже будет включено описание «простыми словами» того, что делает шаблон для целей иллюстрации (благодаря Рэю Хеттингера за документ, который вдохновил большинство описаний). Обратите внимание, что эти описания предназначены исключительно для целей иллюстрации и могут не отражать реализацию на нижнем уровне. Кроме того, они не охватывают все допустимые формы.

8.6.4.1. Шаблоны ИЛИ

Шаблон ИЛИ — это два или более шаблонов, разделенных вертикальными чертами |. Синтаксис:

or_pattern ::=  "|".closed_pattern+

Только конечный подшаблон может быть непреложным, и каждый подшаблон должен связывать тот же набор имён, чтобы избежать неоднозначности.

Шаблон ИЛИ по очереди сопоставляет каждый из своих подшаблонов со значением объекта, пока один из них не увенчается успехом. В таком случае шаблон ИЛИ считается успешным. В противном случае, если ни один из подшаблонов не увенчается успехом, шаблон ИЛИ терпит неудачу.

Проще говоря, P1 | P2 | ... попытается сопоставить P1, если это не удастся, оно попытается сопоставить P2, сразу увенчавшись успехом, если любое из них удастся, в противном случае потерпев неудачу.

8.6.4.2. Шаблоны КАК

Шаблон КАК сопоставляет шаблон ИЛИ слева от ключевого слова as с объектом. Синтаксис:

as_pattern ::=  or_pattern "as" capture_pattern

Если шаблон ИЛИ терпит неудачу, шаблон КАК также терпит неудачу. В противном случае шаблон КАК связывает объект с именем справа от ключевого слова as и увенчивается успехом. capture_pattern не может быть _.

Проще говоря, P as NAME будет соответствовать P, и при успехе оно установит NAME = <subject>.

8.6.4.3. Литеральные Шаблоны

Литеральный шаблон соответствует большинству литералей в Python. Синтаксис:

literal_pattern ::=  signed_number
                     | signed_number "+" NUMBER
                     | signed_number "-" NUMBER
                     | strings
                     | "None"
                     | "True"
                     | "False"
                     | signed_number: NUMBER | "-" NUMBER

Правило strings и токен NUMBER определены в стандартной грамматике Python. Поддерживаются строковые литералы с тройными кавычками. Поддерживаются сырые строки и байтовые строки. Форматированные строковые литералы не поддерживаются.

Формы signed_number '+' NUMBER и signed_number '-' NUMBER предназначены для выражения комплексных чисел; они требуют действительного числа слева и мнимого числа справа. Например, 3 + 4j.

Проще говоря, LITERAL будет успешным только если <subject> == LITERAL. Для единственных элементов None, True и False используется оператор is.

8.6.4.4. Шаблоны Захвата

Шаблон захвата связывает значение объекта с именем. Синтаксис:

capture_pattern ::=  !'_' NAME

Одиночный символ подчеркивания _ не является шаблоном захвата (это то, что выражает !'_'). Вместо этого он обрабатывается как wildcard_pattern.

В данном шаблоне одно и то же имя может быть связано только один раз. Например, case x, x: ... недопустимо, в то время как case [x] | x: ... разрешено.

Шаблоны захвата всегда увенчиваются успехом. Связывание следует правилам области действия, установленным оператором выражения присваивания в PEP 572; имя становится локальной переменной в ближайшем содержащемся вложенном пространстве имён функции, если нет соответствующего global или nonlocal оператора.

Проще говоря, NAME всегда увенчивается успехом, и оно установит NAME = <subject>.

8.6.4.5. Шаблоны Подстановок

Шаблон подстановки всегда увенчивается успехом (сопоставляется со всем) и не связывает ни одного имени. Синтаксис:

wildcard_pattern ::=  '_'

_ является мягким ключевым словом внутри любого шаблона, но только внутри шаблонов. Это идентификатор, как обычно, даже внутри match выражений объекта, guard и case блоков.

Проще говоря, _ всегда увенчается успехом.

8.6.4.6. Шаблоны Значений

Шаблон значения представляет собой именованное значение в Python. Синтаксис:

value_pattern ::=  attr
attr          ::=  name_or_attr "." NAME
name_or_attr  ::=  attr | NAME

Точка с запятой в шаблоне ищется с использованием стандартных правил разрешения имён Python. Шаблон увенчивается успехом, если найденное значение сравнивается по равенству со значением объекта (используя оператор равенства ==).

Проще говоря, NAME1.NAME2 будет успешным только если <subject> == NAME1.NAME2

Примечание

Если одно и то же значение встречается несколько раз в одном и том же операторе сопоставления, интерпретатор может кэшировать первое найденное значение и повторно использовать его, а не повторять тот же поиск. Этот кэш строго связан с данным выполнением данного оператора сопоставления.

8.6.4.7. Шаблоны Групп

Шаблон группы позволяет пользователям добавлять круглые скобки вокруг шаблонов, чтобы подчеркнуть предполагаемую группировку. В противном случае он не имеет дополнительного синтаксиса. Синтаксис:

group_pattern ::=  "(" pattern ")"

Проще говоря, (P) имеет тот же эффект, что и P.

8.6.4.8. Шаблоны Последовательностей

Шаблон последовательности содержит несколько подшаблонов, которые должны быть сопоставлены с элементами последовательности. Синтаксис аналогичен распаковке списка или кортежа.

sequence_pattern       ::=  "[" [maybe_sequence_pattern] "]"
                            | "(" [open_sequence_pattern] ")"
open_sequence_pattern  ::=  maybe_star_pattern "," [maybe_sequence_pattern]
maybe_sequence_pattern ::=  ",".maybe_star_pattern+ ","?
maybe_star_pattern     ::=  star_pattern | pattern
star_pattern           ::=  "*" (capture_pattern | wildcard_pattern)

Разницы нет, если для шаблонов последовательностей используются круглые или квадратные скобки (т.е. (...) против [...]).

Примечание

Один шаблон в круглых скобках без заключительной запятой (например, (3 | 4)) является шаблоном группы. В то время как один шаблон в квадратных скобках (например, [3 | 4]) по-прежнему является шаблоном последовательности.

В шаблоне последовательности может быть не более одного подшаблона со звездочкой. Подшаблон со звездочкой может находиться в любой позиции. Если подшаблон со звездочкой отсутствует, шаблон последовательности является шаблоном последовательности фиксированной длины; в противном случае это шаблон последовательности переменной длины.

Следующее — это логический поток для сопоставления шаблона последовательности со значением объекта:

  1. Если значение объекта не является последовательностью 2, шаблон последовательности терпит неудачу.
  2. Если значение объекта является экземпляром str, bytes или bytearray, шаблон последовательности терпит неудачу.
  3. Следующие шаги зависят от того, является ли шаблон последовательности фиксированной или переменной длины.

    Если шаблон последовательности имеет фиксированную длину:

    1. Если длина последовательности объекта не равна количеству подшаблонов, шаблон последовательности терпит неудачу
    2. Подшаблоны в шаблоне последовательности сопоставляются с соответствующими элементами последовательности объекта слева направо. Сопоставление останавливается, как только подшаблон терпит неудачу. Если все подшаблоны успешно сопоставляются с соответствующим элементом, шаблон последовательности увенчивается успехом.

    В противном случае, если шаблон последовательности имеет переменную длину:

    1. Если длина последовательности объекта меньше числа подшаблонов без звёздочки, шаблон последовательности терпит неудачу.
    2. Ведущие подшаблоны без звёздочки сопоставляются с соответствующими элементами, как для шаблонов последовательностей фиксированной длины.
    3. Если предыдущий шаг увенчался успехом, подшаблон со звездочкой сопоставляет список, образованный оставшимися элементами объекта, исключая оставшиеся элементы, соответствующие подшаблонам без звёздочки, которые следуют за подшаблоном со звездочкой.
    4. Остальные подшаблоны без звёздочки сопоставляются с соответствующими элементами объекта, как для последовательностей фиксированной длины.

    Примечание

    Длина последовательности объекта получается с помощью len() (т.е. через протокол __len__()). Эта длина может быть кэширована интерпретатором аналогичным образом, как шаблоны значений.

Проще говоря, [P1, P2, P3, … , P<N>] сопоставляется только в том случае, если происходит следующее:

  • проверить <subject> является последовательностью
  • len(subject) == <N>
  • P1 соответствует <subject>[0] (обратите внимание, что это сопоставление также может связывать имена)
  • P2 соответствует <subject>[1] (обратите внимание, что это сопоставление также может связывать имена)
  • … и так далее для соответствующего шаблона/элемента.

8.6.4.9. Образцы словарей

Образец словаря содержит один или несколько образцов пар ключ-значение. Синтаксис похож на создание словаря. Синтаксис:

mapping_pattern     ::=  "{" [items_pattern] "}"
items_pattern       ::=  ",".key_value_pattern+ ","?
key_value_pattern   ::=  (literal_pattern | value_pattern) ":" pattern
                         | double_star_pattern
double_star_pattern ::=  "**" capture_pattern

В образце словаря может быть не более одного образца с двойной звездочкой. Образец с двойной звездочкой должен быть последним подобразцом в образце словаря.

Повторяющиеся ключи в образцах словарей запрещены. Повторяющиеся буквальные ключи вызовут SyntaxError. Два ключа с одинаковым значением вызовут ValueError во время выполнения.

Следующий логический поток используется для сопоставления образца словаря со значением объекта:

  1. Если значение объекта не является словарем 3, образец словаря не соответствует.
  2. Если каждый ключ из образца словаря присутствует в словаре-объекте, и образец для каждого ключа соответствует соответствующему элементу словаря-объекта, образец словаря соответствует.
  3. Если обнаружены повторяющиеся ключи в образце словаря, образец считается недействительным. SyntaxError генерируется для повторяющихся буквальных значений; или ValueError для именованных ключей с одинаковыми значениями.

Примечание

Пары ключ-значение сопоставляются с помощью двухаргументной формы метода get() словаря-объекта. Сопоставленные пары ключ-значение должны уже присутствовать в словаре, а не создаваться динамически с помощью __missing__() или __getitem__().

Простыми словами {KEY1: P1, KEY2: P2, ... } соответствует только в том случае, если выполняется следующее:

  • проверка <subject> является словарем
  • KEY1 in <subject>
  • P1 соответствует <subject>[KEY1]
  • … и так далее для соответствующей пары КЛЮЧ/шаблон.

8.6.4.10. Образцы классов

Образец класса представляет класс и его позиционные и ключевые аргументы (если таковые имеются). Синтаксис:

class_pattern       ::=  name_or_attr "(" [pattern_arguments ","?] ")"
pattern_arguments   ::=  positional_patterns ["," keyword_patterns]
                         | keyword_patterns
positional_patterns ::=  ",".pattern+
keyword_patterns    ::=  ",".keyword_pattern+
keyword_pattern     ::=  NAME "=" pattern

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

Следующий логический поток используется для сопоставления образца класса со значением объекта:

  1. Если name_or_attr не является экземпляром встроенного type, генерируется TypeError.
  2. Если значение объекта не является экземпляром name_or_attr (проверяется с помощью isinstance()), образец класса не соответствует.
  3. Если аргументов шаблона нет, шаблон соответствует. В противном случае последующие шаги зависят от наличия образцов ключевых или позиционных аргументов.

    Для ряда встроенных типов (указанных ниже) принимается один позиционный подшаблон, который будет соответствовать всему объекту; для этих типов ключевые шаблоны также работают так же, как и для других типов.

    Если присутствуют только ключевые шаблоны, они обрабатываются по одному:

    I. Ключ ищется как атрибут объекта.

    • Если это вызывает исключение, отличное от AttributeError, исключение поднимается выше.
    • Если это вызывает AttributeError, образец класса не соответствует.
    • В противном случае подшаблон, связанный с ключевым шаблоном, сопоставляется со значением атрибута объекта. Если это не соответствует, образец класса не соответствует; если это соответствует, сопоставление переходит к следующему ключевому аргументу.

    II. Если все ключевые шаблоны соответствуют, образец класса соответствует.

    Если присутствуют какие-либо позиционные шаблоны, они преобразуются в ключевые шаблоны с помощью атрибута __match_args__ класса name_or_attr перед сопоставлением:

    I. Вызывается эквивалент getattr(cls, "__match_args__", ()).

    • Если это вызывает исключение, исключение поднимается выше.
    • Если возвращаемое значение не является кортежем, преобразование завершается неудачей, и генерируется TypeError.
    • Если позиционных шаблонов больше, чем len(cls.__match_args__), генерируется TypeError.
    • В противном случае позиционный шаблон i преобразуется в ключевой шаблон, используя __match_args__[i] в качестве ключевого слова. __match_args__[i] должен быть строкой; в противном случае генерируется TypeError.
    • Если есть повторяющиеся ключевые слова, генерируется TypeError.

    См. также

    Настройка позиционных аргументов в сопоставлении с образцом класса

    II. После преобразования всех позиционных шаблонов в ключевые шаблоны

    сопоставление продолжается так, как будто есть только ключевые шаблоны.

    Для следующих встроенных типов обработка позиционных подшаблонов отличается:

    • bool
    • bytearray
    • bytes
    • dict
    • float
    • frozenset
    • int
    • list
    • set
    • str
    • tuple

    Эти классы принимают один позиционный аргумент, и шаблон в этом случае соответствует всему объекту, а не атрибуту. Например, int(0|1) соответствует значению 0, но не значению 0.0.

Простыми словами CLS(P1, attr=P2) соответствует только в том случае, если выполняется следующее:

  • isinstance(<subject>, CLS)
  • преобразовать P1 в ключевой шаблон с использованием CLS.__match_args__
  • For each keyword argument attr=P2:
    • hasattr(<subject>, "attr")
    • P2 соответствует <subject>.attr
  • … и так далее для соответствующей пары ключевого аргумента/шаблона.

См. также

  • PEP 634 – Спецификация структурного сопоставления с образцами
  • PEP 636 – Руководство по структурному сопоставлению с образцами

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

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

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

Определение функции — это исполняемая инструкция. При его выполнении имя функции в текущем локальном пространстве имен привязывается к объекту функции (обёртке вокруг исполняемого кода функции). Этот объект функции содержит ссылку на текущее глобальное пространство имен как глобальное пространство имен, которое будет использоваться при вызове функции.

Определение функции не выполняет тело функции; это выполняется только при вызове функции. 4

Определение функции может быть обернуто одной или несколькими выражениями декораторов. Выражения декораторов вычисляются при определении функции в области, содержащей определение функции. Результат должен быть вызываемым объектом, который вызывается с объектом функции в качестве единственного аргумента. Возвращаемое значение привязывается к имени функции вместо объекта функции. Несколько декораторов применяются вложенным образом. Например, следующий код

@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__, аннотации сохраняются как строки во время выполнения, что позволяет отложить вычисление. В противном случае они вычисляются при выполнении определения функции. В этом случае аннотации могут быть вычислены в другом порядке, чем в исходном коде.

Также возможно создание анонимных функций (функций, не привязанных к имени), для непосредственного использования в выражениях. Для этого используются выражения lambda, описанные в разделе Lambda. Обратите внимание, что выражение lambda просто сокращённый вариант определения упрощенной функции; функцию, определённую в инструкции «def», можно передавать или присваивать другому имени так же, как функцию, определённую выражением lambda. Форма «def» фактически более мощная, поскольку она позволяет выполнять несколько инструкций и аннотаций.

Примечание для программиста: Функции являются объектами первого класса. Инструкция «def», выполняемая внутри определения функции, определяет вложенную функцию, которую можно возвращать или передавать. Свободные переменные, используемые во вложенной функции, могут получать доступ к локальным переменным функции, содержащей def. См. раздел Именование и привязка для получения подробностей.

См. также

PEP 3107 - Аннотации функций

Исходная спецификация аннотаций функций.

PEP 484 - Типы подсказок

Определение стандартного значения для аннотаций: подсказок типов.

PEP 526 - Синтаксис аннотаций переменных

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

PEP 563 - Отложенное вычисление аннотаций

Поддержка ссылок на будущее в аннотациях путём сохранения аннотаций в строковом виде во время выполнения вместо немедленного вычисления.

8.8. Определения классов

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

classdef    ::=  [decorators] "class" classname [inheritance] ":" suite
inheritance ::=  "(" [argument_list] ")"
classname   ::=  identifier

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

class Foo:
    pass

эквивалентно

class Foo(object):
    pass

Затем тело класса выполняется в новой области выполнения (см. Именование и привязка), используя новое локальное пространство имён и исходное глобальное пространство имён. (Как правило, тело содержит в основном определения функций.) После завершения выполнения тела класса его область выполнения удаляется, но его локальное пространство имён сохраняется. 5 Затем создается объект класса, используя список наследования для базовых классов и сохранённое локальное пространство имён для словаря атрибутов. Имя класса привязывается к этому объекту класса в исходном локальном пространстве имён.

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

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

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

@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.9. Корутины

Введено в версии 3.5.

8.9.1. Определение функции корутины

async_funcdef ::=  [decorators] "async" "def" funcname "(" [parameter_list] ")"
                   ["->" expression] ":" suite

Выполнение Python-корутин может быть приостановлено и возобновлено во многих точках (см. корутина). await выражения, async for и async with могут использоваться только в теле функции корутины.

Функции, определённые с помощью async def синтаксиса, всегда являются функциями корутин, даже если они не содержат await или async ключевых слов.

Использование yield from выражения внутри тела функции корутины является SyntaxError.

Пример функции корутины:

async def func(param1, param2):
    do_stuff()
    await some_coroutine()

Изменено в версии 3.7: await и async теперь являются ключевыми словами; ранее они рассматривались только как таковые внутри тела функции корутины.

8.9.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.9.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

В шаблоне соответствия последовательность определяется как одно из следующих:

  • класс, наследуемый от collections.abc.Sequence
  • класс Python, зарегистрированный как collections.abc.Sequence
  • встроенный класс, у которого установлен бит Py_TPFLAGS_SEQUENCE
  • класс, наследуемый от любого из вышеперечисленных

Следующие стандартные библиотечные классы являются последовательностями:

  • array.array
  • collections.deque
  • list
  • memoryview
  • range
  • tuple

Примечание

Значения типа str, bytes, и bytearray не соответствуют шаблонам последовательностей.

3

В шаблоне соответствия отображение определяется как одно из следующих:

  • класс, наследуемый от collections.abc.Mapping
  • класс Python, зарегистрированный как collections.abc.Mapping
  • встроенный класс, у которого установлен бит Py_TPFLAGS_MAPPING
  • класс, наследуемый от любого из вышеперечисленных

Стандартные библиотечные классы dict и types.MappingProxyType являются отображениями.

4

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

5

Строковый литерал, появляющийся как первое выражение в теле класса, преобразуется в элемент пространства имён __doc__ и, следовательно, в строку документации класса.

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/reference/compound_stmts.html

Spec-Zone.ru

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