# 8. Складені висловлювання

Складені висловлювання містять (групи) інші висловлювання; вони певним чином впливають або контролюють виконання цих інших операторів. Загалом складені висловлювання охоплюють кілька рядків, хоча в простих варіантах ціле складене висловлювання може міститися в одному рядку.

Оператори `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" starred_expression_list ":" suite
              ["else" ":" suite]

The `starred_expression_list` expression is evaluated once; it should yield an iterable object. An iterator is created for that iterable. The first item provided by the iterator is then assigned to the target list using the standard rules for assignments (see Заяви про призначення), and the suite is executed. This repeats for each item provided by the iterator. When the iterator is exhausted, the suite in the `else` clause, if present, is executed, and the loop terminates.

Інструкція `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

Names in the target list are not deleted when the loop is finished, but if the sequence is empty, they will not have been assigned to at all by the loop. Hint: the built-in type `range()` represents immutable arithmetic sequences of integers. For instance, iterating `range(3)` successively yields 0, 1, and then 2.

Змінено в версії 3.11: Starred elements are now allowed in the expression list.

## 8.4. Оператор `try`

The `try` statement specifies exception handlers and/or cleanup code for a group of statements:

    try_stmt:  try1_stmt | try2_stmt | try3_stmt
    try1_stmt: "try" ":" suite
               ("except" [expression ["as" identifier]] ":" suite)+
               ["else" ":" suite]
               ["finally" ":" suite]
    try2_stmt: "try" ":" suite
               ("except" "*" expression ["as" identifier] ":" suite)+
               ["else" ":" suite]
               ["finally" ":" suite]
    try3_stmt: "try" ":" suite
               "finally" ":" suite

Додаткову інформацію про винятки можна знайти в розділі Винятки, а інформацію про використання оператора `raise` для створення винятків можна знайти в розділі Оператор raise.

Змінено в версії 3.14: Support for optionally dropping grouping parentheses when using multiple exception types. See PEP 758.

### 8.4.1. `except` clause

The `except` clause(s) specify one or more exception handlers. When no exception occurs in the `try` clause, no exception handler is executed. When an exception occurs in the `try` suite, a search for an exception handler is started. This search inspects the `except` clauses in turn until one is found that matches the exception. An expression-less `except` clause, if present, must be last; it matches any exception.

For an `except` clause with an expression, the expression must evaluate to an exception type or a tuple of exception types. Parentheses can be dropped if multiple exception types are provided and the `as` clause is not used. The raised exception matches an `except` clause whose expression evaluates to the class or a non-virtual base class of the exception object, or to a tuple that contains such a class.

If no `except` clause matches the exception, the search for an exception handler continues in the surrounding code and on the invocation stack. [1]

If the evaluation of an expression in the header of an `except` clause raises an exception, the original search for a handler is canceled and a search starts for the new exception in the surrounding code and on the call stack (it is treated as if the entire `try` statement raised the exception).

When a matching `except` clause is found, the exception is assigned to the target specified after the `as` keyword in that `except` clause, if present, and the `except` clause’s suite is executed. All `except` clauses must have an executable block. When the end of this block is reached, execution continues normally after the entire `try` statement. (This means that if two nested handlers exist for the same exception, and the exception occurs in the `try` clause of the inner handler, the outer handler will not handle the exception.)

When an exception has been assigned using `as target`, it is cleared at the end of the `except` clause. This is as if

    except E as N:
        foo

було перекладено на:

    except E as N:
        try:
            foo
        finally:
            del N

This means the exception must be assigned to a different name to be able to refer to it after the `except` clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.

Before an `except` clause’s suite is executed, the exception is stored in the `sys` module, where it can be accessed from within the body of the `except` clause by calling `sys.exception()`. When leaving an exception handler, the exception stored in the `sys` module is reset to its previous value:

    >>> print(sys.exception())
    None
    >>> try:
    ...     raise TypeError
    ... except:
    ...     print(repr(sys.exception()))
    ...     try:
    ...          raise ValueError
    ...     except:
    ...         print(repr(sys.exception()))
    ...     print(repr(sys.exception()))
    ...
    TypeError()
    ValueError()
    TypeError()
    >>> print(sys.exception())
    None

### 8.4.2. `except*` clause

The `except*` clause(s) are used for handling `ExceptionGroup`s. The exception type for matching is interpreted as in the case of `except`, but in the case of exception groups we can have partial matches when the type matches some of the exceptions in the group. This means that multiple `except*` clauses can execute, each handling part of the exception group. Each clause executes at most once and handles an exception group of all matching exceptions. Each exception in the group is handled by at most one `except*` clause, the first that matches it.

    >>> try:
    ...     raise ExceptionGroup("eg",
    ...         [ValueError(1), TypeError(2), OSError(3), OSError(4)])
    ... except* TypeError as e:
    ...     print(f'caught {type(e)} with nested {e.exceptions}')
    ... except* OSError as e:
    ...     print(f'caught {type(e)} with nested {e.exceptions}')
    ...
    caught <class 'ExceptionGroup'> with nested (TypeError(2),)
    caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
      + Exception Group Traceback (most recent call last):
      |   File "<stdin>", line 2, in <module>
      | ExceptionGroup: eg
      +-+---------------- 1 ----------------
        | ValueError: 1
        +------------------------------------

Any remaining exceptions that were not handled by any `except*` clause are re-raised at the end, along with all exceptions that were raised from within the `except*` clauses. If this list contains more than one exception to reraise, they are combined into an exception group.

If the raised exception is not an exception group and its type matches one of the `except*` clauses, it is caught and wrapped by an exception group with an empty message string.

    >>> try:
    ...     raise BlockingIOError
    ... except* BlockingIOError as e:
    ...     print(repr(e))
    ...
    ExceptionGroup('', (BlockingIOError()))

An `except*` clause must have a matching expression; it cannot be `except*:`. Furthermore, this expression cannot contain exception group types, because that would have ambiguous semantics.

It is not possible to mix `except` and `except*` in the same `try`. The `break`, `continue`, and `return` statements cannot appear in an `except*` clause.

### 8.4.3. `else` clause

Необов’язкова пропозиція `else` виконується, якщо потік керування виходить із набору `try`, не було викликано винятків і немає `return`, `continue` або Інструкція `break` була виконана. Винятки в пункті `else` не обробляються попередніми пунктами `except`.

### 8.4.4. `finally` clause

If `finally` is present, it specifies a „cleanup“ handler. The `try` clause is executed, including any `except` and `else` clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The `finally` clause is executed. If there is a saved exception it is re-raised at the end of the `finally` clause. If the `finally` clause raises another exception, the saved exception is set as the context of the new exception. If the `finally` clause executes a `return`, `break` or `continue` statement, the saved exception is discarded. For example, this function returns 42.

    def f():
        try:
            1/0
        finally:
            return 42

The exception information is not available to the program during execution of the `finally` clause.

When a `return`, `break` or `continue` statement is executed in the `try` suite of a `try`…`finally` statement, the `finally` clause is also executed „on the way out.“

The return value of a function is determined by the last `return` statement executed. Since the `finally` clause always executes, a `return` statement executed in the `finally` clause will always be the last one executed. The following function returns „finally“.

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

Змінено в версії 3.8: Prior to Python 3.8, a `continue` statement was illegal in the `finally` clause due to a problem with the implementation.

Змінено в версії 3.14: The compiler emits a `SyntaxWarning` when a `return`, `break` or `continue` appears in a `finally` block (see PEP 765).

## 8.5. Оператор `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. The context manager’s `__enter__()` is loaded for later use.

3. The context manager’s `__exit__()` is loaded for later use.

4. The context manager’s `__enter__()` method is invoked.

5. If a target was included in the `with` statement, the return value from `__enter__()` is assigned to it.

   Примітка

   The `with` statement guarantees that if the `__enter__()` method returns without an error, then `__exit__()` will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 7 below.

6. Сюїта виконана.

7. The context manager’s `__exit__()` method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to `__exit__()`. Otherwise, three `None` arguments are supplied.

   If the suite was exited due to an exception, and the return value from the `__exit__()` method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the `with` statement.

   If the suite was exited for any reason other than an exception, the return value from `__exit__()` is ignored, and execution proceeds at the normal location for the kind of exit that was taken.

Наступний код:

    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 - оператор «з».

  Специфікація, передумови та приклади оператора Python `with`.

## 8.6. Оператор `match`

Added in version 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. Огляд

Ось огляд логічної послідовності оператора збігу:

1. Вираз суб’єкта `subject_expr` обчислюється та отримується результуюче значення предмета. Якщо вираз теми містить кому, кортеж створюється за допомогою стандартних правил.

2. Кожен шаблон у `case_block` намагається зіставити зі значенням теми. Конкретні правила успіху чи невдачі описані нижче. Спроба збігу також може пов’язати деякі або всі окремі імена в шаблоні. Точні правила зв’язування шаблону залежать від типу шаблону та вказані нижче. Прив’язки імен, зроблені під час успішного збігу шаблону, переживають виконаний блок і можуть використовуватися після оператора збігу.

   Примітка

   Під час невдалих збігів шаблонів деякі підшаблони можуть бути успішними. Не покладайтеся на прив’язки, зроблені для невдалого матчу. І навпаки, не покладайтеся на те, що змінні залишаться незмінними після невдалого збігу. Точна поведінка залежить від реалізації та може відрізнятися. Це навмисне рішення, яке дозволяє оптимізувати різні реалізації.

3. Якщо шаблон успішний, відповідний охоронець (якщо присутній) оцінюється. У цьому випадку всі прив’язки імен гарантовано відбулися.

   - Якщо guard оцінює як true або відсутній, виконується `block` всередині `case_block`.

   - Інакше виконується спроба наступного `case_block`, як описано вище.

   - Якщо немає інших блоків регістру, оператор збігу завершується.

Примітка

Зазвичай користувачі ніколи не повинні покладатися на шаблон, що оцінюється. Залежно від реалізації, інтерпретатор може кешувати значення або використовувати інші оптимізації, які пропускають повторні оцінки.

Зразок заяви про відповідність:

    >>> 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

`guard` (який є частиною `case`) має бути успішним для виконання коду всередині блоку `case`. Він приймає форму: `if`, після якого йде вираз.

Логічний послідовність блоку `case` з `guard` наступна:

1. Переконайтеся, що шаблон у блоці `case` виконано успішно. Якщо шаблон не вдається, `guard` не оцінюється, і перевіряється наступний `case` блок.

2. Якщо шаблон вдався, оцініть `guard`.

   - Якщо умова `guard` оцінюється як істинна, вибирається блок регістру.

   - Якщо умова `guard` оцінюється як false, блок регістру не вибрано.

   - Якщо `охоронець` викликає виняток під час оцінки, виняток з’являється.

Охоронцям дозволено мати побічні ефекти, оскільки вони є виразами. Оцінка Guard повинна проходити від першого до останнього блоку регістрів, по одному, пропускаючи блоки регістрів, шаблон(и) яких не всі є успішними. (Тобто оцінка охорони має відбуватися в порядку.) Оцінка охорони має припинитися, коли вибрано блок справи.

### 8.6.3. Незаперечні блоки випадків

Незаперечний блок регістрів — це блок регістрів, що відповідає всім регістрам. Інструкція збігу може мати щонайбільше один неспростовний блок регістру, і він має бути останнім.

Блок футляра вважається незаперечним, якщо він не має захисного елемента і його візерунок є неспростовним. Патерн вважається неспростовним, якщо ми можемо довести лише з його синтаксису, що він завжди матиме успіх. Незаперечними є лише такі закономірності:

- AS Patterns, ліва сторона якого неспростовна

- АБО Шаблони, що містить принаймні один неспростовний шаблон

- Захоплення шаблонів

- Шаблони підстановок

- в дужках неспростовні закономірності

### 8.6.4. Візерунки

Примітка

У цьому розділі використовуються граматичні нотації поза стандартними EBNF:

- позначення `SEP.RULE+` є скороченням для `RULE (SEP RULE)*`

- нотація `!RULE` є скороченням для негативного твердження попереднього перегляду

Синтаксис верхнього рівня для `патернів` такий:

    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+

Лише остаточний підшаблон може бути irrefutable, і кожен підшаблон повинен пов’язувати однаковий набір імен, щоб уникнути двозначності.

Шаблон АБО зіставляє кожен зі своїх підшаблонів по черзі зі значенням суб’єкта, поки один не досягне успіху. Потім шаблон АБО вважається успішним. В іншому випадку, якщо жоден із підшаблонів не вдасться, шаблон АБО буде невдалим.

Простіше кажучи, `P1 | P2 | ...` намагатиметься знайти відповідність `P1`, якщо це не вдасться, вона спробує знайти `P2`, успішно негайно, якщо будь-який з них вдасться, інакше не вдасться.

#### 8.6.4.2. AS Patterns

Шаблон AS відповідає шаблону АБО ліворуч від ключового слова `as` щодо теми. Синтаксис:

    as_pattern: or_pattern "as" capture_pattern

If the OR pattern fails, the AS pattern fails. Otherwise, the AS pattern binds the subject to the name on the right of the as keyword and succeeds. `capture_pattern` cannot be a `_`.

Простіше кажучи, `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

The rule `strings` and the token `NUMBER` are defined in the standard Python grammar. Triple-quoted strings are supported. Raw strings and byte strings are supported. f-strings and t-strings are not supported.

Форми `число_знак '+' ЧИСЛО` і `число_знак '-' ЧИСЛО` призначені для вираження комплексних чисел; вони вимагають дійсного числа зліва та уявного числа справа. наприклад `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`s і `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` для іменованих ключів з тим самим значенням.

Примітка

Key-value pairs are matched using the two-argument form of the mapping subject’s `get()` method. Matched key-value pairs must already be present in the mapping, and not created on-the-fly via `__missing__()` or `__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`

   These classes accept a single positional argument, and the pattern there is matched against the whole object rather than an attribute. For example `int(0|1)` matches the value `0`, but not the value `0.0`.

Простіше кажучи, `CLS(P1, attr=P2)` збігається, лише якщо відбувається таке:

- `isinstance( <subject> , CLS)`

- перетворити `P1` на шаблон ключового слова за допомогою `CLS.__match_args__`

- Для кожного аргументу ключового слова `attr=P2`:

  - `hasattr( <subject> , "attr")`

  - `P2` відповідає `<subject> .attr`

- … і так далі для відповідної пари ключового слова аргумент/шаблон.

Дивись також

- PEP 634 – Зіставлення структурних шаблонів: Специфікація

- PEP 636 – Зіставлення структурних шаблонів: підручник

## 8.7. Визначення функцій

Визначення функції визначає об’єкт функції, визначений користувачем (див. розділ Стандартна ієрархія типів):

    funcdef:                   [decorators] "def" funcname [type_params] "(" [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:   "*" [star_parameter] ("," defparameter)* ["," [parameter_star_kwargs]]
                               | "*" ("," defparameter)+ ["," [parameter_star_kwargs]]
                               | parameter_star_kwargs
    parameter_star_kwargs:     "**" parameter [","]
    parameter:                 identifier [":" expression]
    star_parameter:            identifier [":" ["*"] expression]
    defparameter:              parameter ["=" expression]
    funcname:                  identifier

Визначення функції - це виконуваний оператор. Його виконання прив’язує назву функції в поточному локальному просторі імен до об’єкта функції (обгортка навколо виконуваного коду для функції). Цей об’єкт функції містить посилання на поточний глобальний простір імен як глобальний простір імен, який буде використано під час виклику функції.

Визначення функції не виконує тіло функції; це виконується лише під час виклику функції. [4]

Визначення функції може бути обгорнуте одним або кількома виразами decorator. Вирази декоратора обчислюються, коли функція визначена в області видимості, яка містить визначення функції. Результат має бути викликаним, який викликається з об’єктом функції як єдиним аргументом. Повернене значення прив’язується до імені функції замість об’єкта функції. Кілька декораторів застосовуються вкладеним способом. Наприклад, такий код:

    @f1(arg)
    @f2
    def func(): pass

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

    def func(): pass
    func = f1(arg)(f2(func))

за винятком того, що вихідна функція тимчасово не прив’язана до імені `func`.

Змінено в версії 3.9: Функції можуть бути прикрашені будь-яким дійсним `assignment_expression`. Раніше граматика була набагато більш обмежувальною; подробиці див. PEP 614.

A list of type parameters may be given in square brackets between the function’s name and the opening parenthesis for its parameter list. This indicates to static type checkers that the function is generic. At runtime, the type parameters can be retrieved from the function’s `__type_params__` attribute. See Generic functions for more.

Змінено в версії 3.12: Type parameter lists are new in Python 3.12.

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

Значення параметрів за замовчуванням обчислюються зліва направо, коли виконується визначення функції. Це означає, що вираз обчислюється один раз, коли визначається функція, і що те саме «попередньо обчислене» значення використовується для кожного виклику . Це особливо важливо розуміти, коли значення параметра за замовчуванням є змінним об’єктом, таким як список або словник: якщо функція змінює об’єкт (наприклад, шляхом додавання елемента до списку), значення параметра за замовчуванням фактично змінюється. Загалом це не те, що передбачалося. Щоб обійти це, використайте `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.

Parameters may have an annotation of the form «`: expression`» following the parameter name. Any parameter may have an annotation, even those of the form `*identifier` or `**identifier`. (As a special case, parameters of the form `*identifier` may have an annotation «`: *expression`».) Functions may have «return» annotation of the form «`-> expression`» after the parameter list. These annotations can be any valid Python expression. The presence of annotations does not change the semantics of a function. See Annotations for more information on annotations.

Змінено в версії 3.11: Parameters of the form «`*identifier`» may have an annotation «`: *expression`». See PEP 646.

Також можна створювати анонімні функції (функції, не прив’язані до імені) для негайного використання у виразах. Тут використовуються лямбда-вирази, описані в розділі Лямбда. Зауважте, що лямбда-вираз — це лише скорочення спрощеного визначення функції; функція, визначена в операторі «`def`», може бути передана або присвоєна іншому імені так само, як функція, визначена лямбда-виразом. Форма «`def`» насправді є потужнішою, оскільки вона дозволяє виконувати кілька операторів і анотацій.

Примітка програміста: Функції є об’єктами першого класу. Оператор «`def`», який виконується всередині визначення функції, визначає локальну функцію, яку можна повертати або передавати. Вільні змінні, які використовуються у вкладеній функції, можуть отримати доступ до локальних змінних функції, що містить def. Перегляньте розділ Називання та зв’язування для деталей.

Дивись також

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

  Оригінальна специфікація для анотацій функцій.

PEP 484 - підказки типу

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

PEP 526 - Синтаксис для анотацій змінних

  Ability to type hint variable declarations, including class variables and instance variables.

PEP 563 - Відкладена оцінка анотацій

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

PEP 318 - Decorators for Functions and Methods

  Function and method decorators were introduced. Class decorators were introduced in PEP 3129.

## 8.8. Визначення класів

Визначення класу визначає об’єкт класу (див. розділ Стандартна ієрархія типів):

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

Визначення класу є виконуваним оператором. Список успадкування зазвичай надає список базових класів (див. Метакласи для більш просунутого використання), тому кожен елемент у списку повинен оцінюватися як об’єкт класу, який дозволяє створювати підкласи. Класи без списку успадкування успадковують, за замовчуванням, від базового класу `object`; отже,

    class Foo:
        pass

еквівалентно

    class Foo(object):
        pass

There may be one or more base classes; see Multiple inheritance below for more information.

Потім набір класів виконується в новому фреймі виконання (див. Називання та зв’язування), використовуючи щойно створений локальний простір імен і оригінальний глобальний простір імен. (Зазвичай набір містить в основному визначення функцій.) Коли набір класу завершує виконання, його кадр виконання відкидається, але його локальний простір імен зберігається. [5] Потім створюється об’єкт класу з використанням списку успадкування для базових класів і збереженого локального простору імен для словника атрибутів. Ім’я класу прив’язане до цього об’єкта класу в оригінальному локальному просторі імен.

The order in which attributes are defined in the class body is preserved in the new class’s `__dict__`. Note that this is reliable only right after the class is created and only for classes that were defined using the definition syntax.

Створення класів можна значно налаштувати за допомогою metaclasses.

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

    @f1(arg)
    @f2
    class Foo: pass

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

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

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

Змінено в версії 3.9: Класи можуть бути прикрашені будь-яким дійсним `assignment_expression`. Раніше граматика була набагато більш обмежувальною; подробиці див. PEP 614.

A list of type parameters may be given in square brackets immediately after the class’s name. This indicates to static type checkers that the class is generic. At runtime, the type parameters can be retrieved from the class’s `__type_params__` attribute. See Generic classes for more.

Змінено в версії 3.12: Type parameter lists are new in Python 3.12.

Примітка програміста: Змінні, визначені у визначенні класу, є атрибутами класу; їх ділять інстанції. Атрибути екземпляра можна встановити в методі за допомогою `self.name = value`. Як атрибути класу, так і атрибути екземпляра доступні через нотацію «`self.name`», а атрибут екземпляра приховує атрибут класу з таким самим іменем, коли до нього звертаються таким чином. Атрибути класу можна використовувати як значення за замовчуванням для атрибутів екземплярів, але використання там змінних значень може призвести до неочікуваних результатів. Дескриптори можна використовувати для створення змінних екземпляра з різними деталями реалізації.

Дивись також

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

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

PEP 3129 - Декоратори класу

  Пропозиція, яка додала декоратори класу. Декоратори функцій і методів були представлені в PEP 318.

### 8.8.1. Multiple inheritance

Python classes may have multiple base classes, a technique known as multiple inheritance. The base classes are specified in the class definition by listing them in parentheses after the class name, separated by commas. For example, the following class definition:

    >>> class A: pass
    >>> class B: pass
    >>> class C(A, B): pass

defines a class `C` that inherits from classes `A` and `B`.

The method resolution order (MRO) is the order in which base classes are searched when looking up an attribute on a class. See The Python 2.3 Method Resolution Order for a description of how Python determines the MRO for a class.

Multiple inheritance is not always allowed. Attempting to define a class with multiple inheritance will raise an error if one of the bases does not allow subclassing, if a consistent MRO cannot be created, if no valid metaclass can be determined, or if there is an instance layout conflict. We’ll discuss each of these in turn.

First, all base classes must allow subclassing. While most classes allow subclassing, some built-in classes do not, such as `bool`:

    >>> class SubBool(bool):  # TypeError
    ...    pass
    Traceback (most recent call last):
       ...
    TypeError: type 'bool' is not an acceptable base type

In the resolved MRO of a class, the class’s bases appear in the order they were specified in the class’s bases list. Additionally, the MRO always lists a child class before any of its bases. A class definition will fail if it is impossible to resolve a consistent MRO that satisfies these rules from the list of bases provided:

    >>> class Base: pass
    >>> class Child(Base): pass
    >>> class Grandchild(Base, Child): pass  # TypeError
    Traceback (most recent call last):
       ...
    TypeError: Cannot create a consistent method resolution order (MRO) for bases Base, Child

In the MRO of `Grandchild`, `Base` must appear before `Child` because it is first in the base class list, but it must also appear after `Child` because it is a parent of `Child`. This is a contradiction, so the class cannot be defined.

If some of the bases have a custom metaclass, the metaclass of the resulting class is chosen among the metaclasses of the bases and the explicitly specified metaclass of the child class. It must be a metaclass that is a subclass of all other candidate metaclasses. If no such metaclass exists among the candidates, the class cannot be created, as explained in Визначення відповідного метакласу.

Finally, the instance layouts of the bases must be compatible. This means that it must be possible to compute a solid base for the class. Exactly which classes are solid bases depends on the Python implementation.

Деталі реалізації CPython: In CPython, a class is a solid base if it has a nonempty `__slots__` definition. Many but not all classes defined in C are also solid bases, including most builtins (such as `int` or `BaseException`) but excluding most concrete `Exception` classes. Generally, a C class is a solid base if its underlying struct is different in size from its base class.

Every class has a solid base. `object`, the base class, has itself as its solid base. If there is a single base, the child class’s solid base is that class if it is a solid base, or else the base class’s solid base. If there are multiple bases, we first find the solid base for each base class to produce a list of candidate solid bases. If there is a unique solid base that is a subclass of all others, then that class is the solid base. Otherwise, class creation fails.

Example:

    >>> class Solid1:
    ...    __slots__ = ("solid1",)
    >>>
    >>> class Solid2:
    ...    __slots__ = ("solid2",)
    >>>
    >>> class SolidChild(Solid1):
    ...    __slots__ = ("solid_child",)
    >>>
    >>> class C1:  # solid base is `object`
    ...    pass
    >>>
    >>> # OK: solid bases are `Solid1` and `object`, and `Solid1` is a subclass of `object`.
    >>> class C2(Solid1, C1):  # solid base is `Solid1`
    ...    pass
    >>>
    >>> # OK: solid bases are `SolidChild` and `Solid1`, and `SolidChild` is a subclass of `Solid1`.
    >>> class C3(SolidChild, Solid1):  # solid base is `SolidChild`
    ...    pass
    >>>
    >>> # Error: solid bases are `Solid1` and `Solid2`, but neither is a subclass of the other.
    >>> class C4(Solid1, Solid2):  # error: no single solid base
    ...    pass
    Traceback (most recent call last):
      ...
    TypeError: multiple bases have instance lay-out conflict

## 8.9. Співпрограми

Added in version 3.5.

### 8.9.1. Визначення функції співпрограми

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

Виконання співпрограм Python можна призупинити та відновити в багатьох точках (див. coroutine). Вирази `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

asynchronous iterable надає метод `__aiter__`, який безпосередньо повертає asynchronous iterator, який може викликати асинхронний код у своєму методі `__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

See also `__aiter__()` and `__anext__()` for details.

Це `SyntaxError`, якщо використовувати оператор `async for` поза тілом функції співпрограми.

### 8.9.3. Оператор `async with`

    async_with_stmt: "async" with_stmt

Асинхронний менеджер контексту (asynchronous context manager) — це менеджер контексту (context manager),який може призупинити виконання своїх методів 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)

See also `__aenter__()` and `__aexit__()` for details.

Це `SyntaxError`, якщо використовувати оператор `async with` поза тілом функції співпрограми.

Дивись також

PEP 492 - Співпрограми з синтаксисом async і await

  Пропозиція, яка зробила співпрограми справжньою автономною концепцією в Python і додала допоміжний синтаксис.

## 8.10. Type parameter lists

Added in version 3.12.

Змінено в версії 3.13: Support for default values was added (see PEP 696).

    type_params:  "[" type_param ("," type_param)* "]"
    type_param:   typevar | typevartuple | paramspec
    typevar:      identifier (":" expression)? ("=" expression)?
    typevartuple: "*" identifier ("=" expression)?
    paramspec:    "**" identifier ("=" expression)?

Functions (including coroutines), classes and type aliases may contain a type parameter list:

    def max[T](args: list[T]) -> T:
        ...

    async def amax[T](args: list[T]) -> T:
        ...

    class Bag[T]:
        def __iter__(self) -> Iterator[T]:
            ...

        def add(self, arg: T) -> None:
            ...

    type ListOrSet[T] = list[T] | set[T]

Semantically, this indicates that the function, class, or type alias is generic over a type variable. This information is primarily used by static type checkers, and at runtime, generic objects behave much like their non-generic counterparts.

Type parameters are declared in square brackets (`[]`) immediately after the name of the function, class, or type alias. The type parameters are accessible within the scope of the generic object, but not elsewhere. Thus, after a declaration `def func[T](): pass`, the name `T` is not available in the module scope. Below, the semantics of generic objects are described with more precision. The scope of type parameters is modeled with a special function (technically, an annotation scope) that wraps the creation of the generic object.

Generic functions, classes, and type aliases have a `__type_params__` attribute listing their type parameters.

Type parameters come in three kinds:

- `typing.TypeVar`, introduced by a plain name (e.g., `T`). Semantically, this represents a single type to a type checker.

- `typing.TypeVarTuple`, introduced by a name prefixed with a single asterisk (e.g., `*Ts`). Semantically, this stands for a tuple of any number of types.

- `typing.ParamSpec`, introduced by a name prefixed with two asterisks (e.g., `**P`). Semantically, this stands for the parameters of a callable.

`typing.TypeVar` declarations can define bounds and constraints with a colon (`:`) followed by an expression. A single expression after the colon indicates a bound (e.g. `T: int`). Semantically, this means that the `typing.TypeVar` can only represent types that are a subtype of this bound. A parenthesized tuple of expressions after the colon indicates a set of constraints (e.g. `T: (str, bytes)`). Each member of the tuple should be a type (again, this is not enforced at runtime). Constrained type variables can only take on one of the types in the list of constraints.

For `typing.TypeVar`s declared using the type parameter list syntax, the bound and constraints are not evaluated when the generic object is created, but only when the value is explicitly accessed through the attributes `__bound__` and `__constraints__`. To accomplish this, the bounds or constraints are evaluated in a separate annotation scope.

`typing.TypeVarTuple`s and `typing.ParamSpec`s cannot have bounds or constraints.

All three flavors of type parameters can also have a default value, which is used when the type parameter is not explicitly provided. This is added by appending a single equals sign (`=`) followed by an expression. Like the bounds and constraints of type variables, the default value is not evaluated when the object is created, but only when the type parameter’s `__default__` attribute is accessed. To this end, the default value is evaluated in a separate annotation scope. If no default value is specified for a type parameter, the `__default__` attribute is set to the special sentinel object `typing.NoDefault`.

The following example indicates the full set of allowed type parameter declarations:

    def overly_generic[
       SimpleTypeVar,
       TypeVarWithDefault = int,
       TypeVarWithBound: int,
       TypeVarWithConstraints: (str, bytes),
       *SimpleTypeVarTuple = (int, float),
       **SimpleParamSpec = (str, bytearray),
    ](
       a: SimpleTypeVar,
       b: TypeVarWithDefault,
       c: TypeVarWithBound,
       d: Callable[SimpleParamSpec, TypeVarWithConstraints],
       *e: SimpleTypeVarTuple,
    ): ...

### 8.10.1. Generic functions

Generic functions are declared as follows:

    def func[T](arg: T): ...

This syntax is equivalent to:

    annotation-def TYPE_PARAMS_OF_func():
        T = typing.TypeVar("T")
        def func(arg: T): ...
        func.__type_params__ = (T,)
        return func
    func = TYPE_PARAMS_OF_func()

Here `annotation-def` indicates an annotation scope, which is not actually bound to any name at runtime. (One other liberty is taken in the translation: the syntax does not go through attribute access on the `typing` module, but creates an instance of `typing.TypeVar` directly.)

The annotations of generic functions are evaluated within the annotation scope used for declaring the type parameters, but the function’s defaults and decorators are not.

The following example illustrates the scoping rules for these cases, as well as for additional flavors of type parameters:

    @decorator
    def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):
        ...

Except for the lazy evaluation of the `TypeVar` bound, this is equivalent to:

    DEFAULT_OF_arg = some_default

    annotation-def TYPE_PARAMS_OF_func():

        annotation-def BOUND_OF_T():
            return int
        # In reality, BOUND_OF_T() is evaluated only on demand.
        T = typing.TypeVar("T", bound=BOUND_OF_T())

        Ts = typing.TypeVarTuple("Ts")
        P = typing.ParamSpec("P")

        def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):
            ...

        func.__type_params__ = (T, Ts, P)
        return func
    func = decorator(TYPE_PARAMS_OF_func())

The capitalized names like `DEFAULT_OF_arg` are not actually bound at runtime.

### 8.10.2. Generic classes

Generic classes are declared as follows:

    class Bag[T]: ...

This syntax is equivalent to:

    annotation-def TYPE_PARAMS_OF_Bag():
        T = typing.TypeVar("T")
        class Bag(typing.Generic[T]):
            __type_params__ = (T,)
            ...
        return Bag
    Bag = TYPE_PARAMS_OF_Bag()

Here again `annotation-def` (not a real keyword) indicates an annotation scope, and the name `TYPE_PARAMS_OF_Bag` is not actually bound at runtime.

Generic classes implicitly inherit from `typing.Generic`. The base classes and keyword arguments of generic classes are evaluated within the type scope for the type parameters, and decorators are evaluated outside that scope. This is illustrated by this example:

    @decorator
    class Bag(Base[T], arg=T): ...

Це еквівалентно:

    annotation-def TYPE_PARAMS_OF_Bag():
        T = typing.TypeVar("T")
        class Bag(Base[T], typing.Generic[T], arg=T):
            __type_params__ = (T,)
            ...
        return Bag
    Bag = decorator(TYPE_PARAMS_OF_Bag())

### 8.10.3. Generic type aliases

The `type` statement can also be used to create a generic type alias:

    type ListOrSet[T] = list[T] | set[T]

Except for the lazy evaluation of the value, this is equivalent to:

    annotation-def TYPE_PARAMS_OF_ListOrSet():
        T = typing.TypeVar("T")

        annotation-def VALUE_OF_ListOrSet():
            return list[T] | set[T]
        # In reality, the value is lazily evaluated
        return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))
    ListOrSet = TYPE_PARAMS_OF_ListOrSet()

Here, `annotation-def` (not a real keyword) indicates an annotation scope. The capitalized names like `TYPE_PARAMS_OF_ListOrSet` are not actually bound at runtime.

## 8.11. Annotations

Змінено в версії 3.14: Annotations are now lazily evaluated by default.

Variables and function parameters may carry annotations, created by adding a colon after the name, followed by an expression:

    x: annotation = 1
    def f(param: annotation): ...

Functions may also carry a return annotation following an arrow:

    def f() -> annotation: ...

Annotations are conventionally used for type hints, but this is not enforced by the language, and in general annotations may contain arbitrary expressions. The presence of annotations does not change the runtime semantics of the code, except if some mechanism is used that introspects and uses the annotations (such as `dataclasses` or `functools.singledispatch()`).

By default, annotations are lazily evaluated in an annotation scope. This means that they are not evaluated when the code containing the annotation is evaluated. Instead, the interpreter saves information that can be used to evaluate the annotation later if requested. The `annotationlib` module provides tools for evaluating annotations.

If the future statement `from __future__ import annotations` is present, all annotations are instead stored as strings:

    >>> from __future__ import annotations
    >>> def f(param: annotation): ...
    >>> f.__annotations__
    {'param': 'annotation'}

This future statement will be deprecated and removed in a future version of Python, but not before Python 3.13 reaches its end of life (see PEP 749). When it is used, introspection tools like `annotationlib.get_annotations()` and `typing.get_type_hints()` are less likely to be able to resolve annotations at runtime.

Виноски

[ 1 ]

Виняток поширюється на стек викликів, якщо немає пункту `finally`, який викликає інший виняток. Цей новий виняток призводить до втрати старого.

[ 2 ]

У відповідності за зразком послідовність визначається як одне з наступного:

- клас, який успадковує `collections.abc.Sequence`

- клас Python, зареєстрований як `collections.abc.Sequence`

- a builtin class that has its (CPython) `Py_TPFLAGS_SEQUENCE` bit set

- клас, який успадковує будь-який з перерахованих вище

Наступні стандартні бібліотечні класи є послідовностями:

- `array.array`

- `collections.deque`

- `list`

- `memoryview`

- `range`

- `tuple`

Примітка

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

[ 3 ]

У відповідності за шаблоном відображення визначається як одне з наступного:

- клас, який успадковує `collections.abc.Mapping`

- клас Python, зареєстрований як `collections.abc.Mapping`

- a builtin class that has its (CPython) `Py_TPFLAGS_MAPPING` bit set

- клас, який успадковує будь-який з перерахованих вище

Класи стандартної бібліотеки `dict` і `types.MappingProxyType` є відображеннями.

[ 4 ]

A string literal appearing as the first statement in the function body is transformed into the function’s `__doc__` attribute and therefore the function’s docstring.

[ 5 ]

A string literal appearing as the first statement in the class body is transformed into the namespace’s `__doc__` item and therefore the class’s docstring.