# 7. Прості твердження

Просте твердження міститься в одному логічному рядку. В одному рядку, розділених крапкою з комою, може бути кілька простих операторів. Синтаксис простих операторів такий:

    simple_stmt: expression_stmt
                 | assert_stmt
                 | assignment_stmt
                 | augmented_assignment_stmt
                 | annotated_assignment_stmt
                 | pass_stmt
                 | del_stmt
                 | return_stmt
                 | yield_stmt
                 | raise_stmt
                 | break_stmt
                 | continue_stmt
                 | import_stmt
                 | future_stmt
                 | global_stmt
                 | nonlocal_stmt
                 | type_stmt

## 7.1. Вирази

Інструкції-вирази використовуються (здебільшого в інтерактивному режимі) для обчислення та запису значення або (зазвичай) для виклику процедури (функції, яка не повертає значущого результату; у Python процедури повертають значення `None`). Інші способи використання операторів-виразів дозволені та інколи корисні. Синтаксис оператора виразу:

    expression_stmt: starred_expression

Оператор виразу обчислює список виразів (який може бути одним виразом).

В інтерактивному режимі, якщо значення не є `None`, воно перетворюється на рядок за допомогою вбудованої функції `repr()`, а отриманий рядок записується до стандартного виводу в окремому рядку (крім випадків, коли результатом є `None`, так що виклики процедур не викликають жодних виводів.)

## 7.2. Заяви про призначення

Оператори присвоєння використовуються для (повторного) прив’язування імен до значень і для зміни атрибутів або елементів змінних об’єктів:

    assignment_stmt: (target_list "=")+ (starred_expression | yield_expression)
    target_list:     target ("," target)* [","]
    target:          identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | "*" target

(See section Праймеріз for the syntax definitions for attributeref and subscription.)

Інструкція присвоєння оцінює список виразів (пам’ятайте, що це може бути один вираз або список, розділений комами, останній дає кортеж) і призначає єдиний результуючий об’єкт кожному з цільових списків зліва направо.

Assignment is defined recursively depending on the form of the target (list). When a target is part of a mutable object (an attribute reference or subscription), the mutable object must ultimately perform the assignment and decide about its validity, and may raise an exception if the assignment is unacceptable. The rules observed by various types and the exceptions raised are given with the definition of the object types (see section Стандартна ієрархія типів).

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

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

- ще:

  - Якщо цільовий список містить одну ціль із префіксом зірочки, це називається ціль із зірочкою: об’єкт має бути ітерованим із принаймні такою кількістю елементів, скільки цілей у списку цілей, мінус один. Перші елементи iterable призначаються, зліва направо, цілям перед ціллю, позначеною зірочкою. Останні елементи iterable призначаються цілям після цілі, позначеної зірочкою. Список елементів, що залишилися в iterable, потім призначається позначеній цілі (список може бути порожнім).

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

Призначення об’єкта одній меті рекурсивно визначається наступним чином.

- Якщо метою є ідентифікатор (ім’я):

  - Якщо ім’я не зустрічається в операторі `global` або `nonlocal` у поточному блоці коду: ім’я прив’язується до об’єкта в поточному локальному просторі імен.

  - Інакше: ім’я прив’язується до об’єкта в глобальному просторі імен або зовнішньому просторі імен, визначеному `nonlocal` відповідно.

  Ім’я повертається, якщо воно вже було зв’язане. Це може призвести до того, що кількість посилань для об’єкта, раніше прив’язаного до імені, досягне нуля, що призведе до звільнення об’єкта та виклику його деструктора (якщо він є).

- Якщо метою є посилання на атрибут: обчислюється основний вираз у посиланні. Він повинен давати об’єкт із присвоюваними атрибутами; якщо це не так, виникає `TypeError`. Тоді цей об’єкт запитується призначити призначений об’єкт даному атрибуту; якщо він не може виконати призначення, він викликає виняток (зазвичай, але не обов’язково `AttributeError`).

  Примітка. Якщо об’єкт є екземпляром класу, а посилання на атрибут міститься з обох сторін оператора присвоєння, вираз у правому боці `a.x` може отримати доступ або до атрибута екземпляра, або (якщо атрибут екземпляра не існує) до класу атрибут. Ліва ціль `a.x` завжди встановлюється як атрибут екземпляра, створюючи його за необхідності. Таким чином, два входження `a.x` не обов’язково посилаються на той самий атрибут: якщо правий вираз посилається на атрибут класу, ліва частина створює новий атрибут екземпляра як ціль призначення: :

      class Cls:
          x = 3             # class variable
      inst = Cls()
      inst.x = inst.x + 1   # writes inst.x as 4 leaving Cls.x as 3

  Цей опис не обов’язково стосується атрибутів дескрипторів, таких як властивості, створені за допомогою `property()`.

- If the target is a subscription: The primary expression in the reference is evaluated. Next, the subscript expression is evaluated. Then, the primary’s `__setitem__()` method is called with two arguments: the subscript and the assigned object.

  Typically, `__setitem__()` is defined on mutable sequence objects (such as lists) and mapping objects (such as dictionaries), and behaves as follows.

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

  If the primary is a mapping object (such as a dictionary), the subscript must have a type compatible with the mapping’s key type, and the mapping is then asked to create a key/value pair which maps the subscript to the assigned object. This can either replace an existing key/value pair with the same key value, or insert a new key/value pair (if no key with the same value existed).

  If the target is a slicing: The primary expression should evaluate to a mutable sequence object (such as a list). The assigned object should be iterable. The slicing’s lower and upper bounds should be integers; if they are `None` (or not present), the defaults are zero and the sequence’s length. If either bound is negative, the sequence’s length is added to it. The resulting bounds are clipped to lie between zero and the sequence’s length, inclusive. Finally, the sequence object is asked to replace the slice with the items of the assigned sequence. The length of the slice may be different from the length of the assigned sequence, thus changing the length of the target sequence, if the target sequence allows it.

Хоча визначення присвоєння передбачає, що збіги між лівою та правою сторонами є «одночасними» (наприклад, `a, b = b, a` міняє місцями дві змінні), збіги в колекції присвоєні змінним відбуваються зліва направо, що іноді призводить до плутанини. Наприклад, наступна програма друкує `[0, 2]`:

    x = [0, 1]
    i = 0
    i, x[i] = 1, 2         # i is updated, then x[i] is updated
    print(x)

Дивись також

PEP 3132 - Розширене ітераційне розпакування

  Специфікація функції `*target`.

### 7.2.1. Доповнені заяви про призначення

Розширене присвоєння — це комбінація в одному операторі двійкової операції та оператора присвоєння:

    augmented_assignment_stmt: augtarget augop (expression_list | yield_expression)
    augtarget:                 identifier | attributeref | subscription
    augop:                     "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
                               | ">>=" | "<<=" | "&=" | "^=" | "|="

(Див. розділ Праймеріз для визначення синтаксису останніх трьох символів.)

Розширене призначення оцінює ціль (яка, на відміну від звичайних операторів призначення, не може бути розпаковуванням) і список виразів, виконує двійкову операцію, специфічну для типу призначення над двома операндами, і призначає результат вихідній цільовій цілі. Ціль оцінюється лише один раз.

An augmented assignment statement like `x += 1` can be rewritten as `x = x + 1` to achieve a similar, but not exactly equal effect. In the augmented version, `x` is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.

На відміну від звичайних завдань, розширені завдання оцінюють ліву сторону перед оцінкою правої сторони. Наприклад, `a[i] += f(x)` спочатку шукає `a[i]`, потім обчислює `f(x)` і виконує додавання, і, нарешті, він записує результат назад до `a[i]`.

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

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

### 7.2.2. Анотовані заяви про призначення

Анотація присвоєння — це комбінація в одному операторі анотації змінної або атрибута та необов’язкового оператора призначення:

    annotated_assignment_stmt: augtarget ":" expression
                               ["=" (starred_expression | yield_expression)]

The difference from normal Заяви про призначення is that only a single target is allowed.

The assignment target is considered «simple» if it consists of a single name that is not enclosed in parentheses. For simple assignment targets, if in class or module scope, the annotations are gathered in a lazily evaluated annotation scope. The annotations can be evaluated using the `__annotations__` attribute of a class or module, or using the facilities in the `annotationlib` module.

If the assignment target is not simple (an attribute, subscript node, or parenthesized name), the annotation is never evaluated.

Якщо ім’я анотовано в області видимості функції, то це ім’я є локальним для цієї області. Анотації ніколи не оцінюються та зберігаються в областях функцій.

If the right hand side is present, an annotated assignment performs the actual assignment as if there was no annotation present. If the right hand side is not present for an expression target, then the interpreter evaluates the target except for the last `__setitem__()` or `__setattr__()` call.

Дивись також

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

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

PEP 484 - Тип підказок

  Пропозиція, яка додала модуль `typing`, щоб забезпечити стандартний синтаксис для анотацій типів, які можна використовувати в інструментах статичного аналізу та IDE.

Змінено в версії 3.8: Now annotated assignments allow the same expressions in the right hand side as regular assignments. Previously, some expressions (like un-parenthesized tuple expressions) caused a syntax error.

Змінено в версії 3.14: Annotations are now lazily evaluated in a separate annotation scope. If the assignment target is not simple, annotations are never evaluated.

## 7.3. Оператор `assert`

Оператори Assert — це зручний спосіб вставити в програму твердження налагодження:

    assert_stmt: "assert" expression ["," expression]

Проста форма, `assert expression`, еквівалентна

    if __debug__:
        if not expression: raise AssertionError

Розширена форма, `assert expression1, expression2`, еквівалентна

    if __debug__:
        if not expression1: raise AssertionError(expression2)

These equivalences assume that `__debug__` and `AssertionError` refer to the built-in variables with those names. In the current implementation, the built-in variable `__debug__` is `True` under normal circumstances, `False` when optimization is requested (command line option `-O`). The current code generator emits no code for an `assert` statement when optimization is requested at compile time. Note that it is unnecessary to include the source code for the expression that failed in the error message; it will be displayed as part of the stack trace.

Присвоєння `__debug__` є незаконним. Значення для вбудованої змінної визначається під час запуску інтерпретатора.

## 7.4. Оператор `pass`

    pass_stmt: "pass"

`pass` є нульовою операцією — коли вона виконується, нічого не відбувається. Це корисно як заповнювач, коли оператор потрібний синтаксично, але не потрібно виконувати код, наприклад:

    def f(arg): pass    # a function that does nothing (yet)

    class C: pass       # a class with no methods (yet)

## 7.5. Оператор `del`

    del_stmt: "del" target_list

Видалення рекурсивно визначається дуже подібно до того, як визначається призначення. Замість того, щоб викладати все детально, ось кілька підказок.

Видалення списку цілей рекурсивно видаляє кожну ціль зліва направо.

Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a `global` statement in the same code block. Trying to delete an unbound name raises a `NameError` exception.

Deletion of attribute references and subscriptions is passed to the primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object).

Змінено в версії 3.2: Раніше було заборонено видаляти ім’я з локального простору імен, якщо воно зустрічається як вільна змінна у вкладеному блоці.

## 7.6. Оператор `return`

    return_stmt: "return" [expression_list]

`return` може бути лише синтаксично вкладеним у визначення функції, а не у визначенні вкладеного класу.

Якщо присутній список виразів, він обчислюється, інакше замінюється `None`.

`return` залишає поточний виклик функції зі списком виразів (або `None`) як значення повернення.

Коли `return` передає керування оператору `try` з пропозицією `finally`, ця пропозиція `finally` виконується перед фактичним виходом із функції.

У функції генератора оператор `return` вказує на те, що генератор завершено та спричинить виклик `StopIteration`. Повернене значення (за наявності) використовується як аргумент для створення `StopIteration` і стає атрибутом `StopIteration.value`.

У функції асинхронного генератора порожній оператор `return` вказує на те, що асинхронний генератор завершено та призведе до виклику `StopAsyncIteration`. Непорожній оператор `return` є синтаксичною помилкою у функції асинхронного генератора.

## 7.7. Оператор `yield`

    yield_stmt: yield_expression

A `yield` statement is semantically equivalent to a yield expression. The `yield` statement can be used to omit the parentheses that would otherwise be required in the equivalent yield expression statement. For example, the yield statements

    yield <expr>
    yield from <expr>

еквівалентні операторам виразу yield

    (yield <expr>)
    (yield from <expr>)

Yield expressions and statements are only used when defining a generator function, and are only used in the body of the generator function. Using `yield` in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.

Щоб отримати повну інформацію про семантику `yield`, зверніться до розділу Вирази дохідності.

## 7.8. Оператор `raise`

    raise_stmt: "raise" [expression ["from" expression]]

Якщо виразів немає, `raise` повторно викликає виняток, який зараз обробляється, який також відомий як активний виняток. Якщо наразі немає активного винятку, виникає виняток `RuntimeError`, який вказує на те, що це помилка.

В іншому випадку `raise` обчислює перший вираз як об’єкт винятку. Це має бути або підклас, або екземпляр `BaseException`. Якщо це клас, екземпляр винятку буде отримано за потреби шляхом створення екземпляра класу без аргументів.

type винятку — це клас екземпляра винятку, value — це сам екземпляр.

A traceback object is normally created automatically when an exception is raised and attached to it as the `__traceback__` attribute. You can create an exception and set your own traceback in one step using the `with_traceback()` exception method (which returns the same exception instance, with its traceback set to its argument), like so:

    raise Exception("foo occurred").with_traceback(tracebackobj)

The `from` clause is used for exception chaining: if given, the second expression must be another exception class or instance. If the second expression is an exception instance, it will be attached to the raised exception as the `__cause__` attribute (which is writable). If the expression is an exception class, the class will be instantiated and the resulting exception instance will be attached to the raised exception as the `__cause__` attribute. If the raised exception is not handled, both exceptions will be printed:

    >>> try:
    ...     print(1 / 0)
    ... except Exception as exc:
    ...     raise RuntimeError("Something bad happened") from exc
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
        print(1 / 0)
              ~~^~~
    ZeroDivisionError: division by zero

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
        raise RuntimeError("Something bad happened") from exc
    RuntimeError: Something bad happened

A similar mechanism works implicitly if a new exception is raised when an exception is already being handled. An exception may be handled when an `except` or `finally` clause, or a `with` statement, is used. The previous exception is then attached as the new exception’s `__context__` attribute:

    >>> try:
    ...     print(1 / 0)
    ... except:
    ...     raise RuntimeError("Something bad happened")
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
        print(1 / 0)
              ~~^~~
    ZeroDivisionError: division by zero

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
        raise RuntimeError("Something bad happened")
    RuntimeError: Something bad happened

Exception chaining can be explicitly suppressed by specifying `None` in the `from` clause:

    >>> try:
    ...     print(1 / 0)
    ... except:
    ...     raise RuntimeError("Something bad happened") from None
    ...
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    RuntimeError: Something bad happened

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

Змінено в версії 3.3: `None` тепер дозволено як `Y` у `raise X from Y`.

Added the `__suppress_context__` attribute to suppress automatic display of the exception context.

Змінено в версії 3.11: If the traceback of the active exception is modified in an `except` clause, a subsequent `raise` statement re-raises the exception with the modified traceback. Previously, the exception was re-raised with the traceback it had when it was caught.

## 7.9. Оператор `break`

    break_stmt: "break"

`break` може бути лише синтаксично вкладеним у циклі `for` або `while`, але не вкладеним у визначення функції чи класу в цьому циклі.

Він завершує найближчий охоплюючий цикл, пропускаючи необов’язкову пропозицію `else`, якщо вона є в циклі.

Якщо цикл `for` завершується `break`, мета керування циклом зберігає своє поточне значення.

Коли `break` передає керування оператору `try` з пропозицією `finally`, ця пропозиція `finally` виконується перед тим, як фактично вийти з циклу.

## 7.10. Оператор `continue`

    continue_stmt: "continue"

`continue` може бути лише синтаксично вкладеним у циклі `for` або `while`, але не вкладеним у визначення функції чи класу в цьому циклі. Він продовжується наступним циклом найближчого охоплюючого циклу.

Коли `continue` передає керування оператору `try` з пропозицією `finally`, ця пропозиція `finally` виконується перед тим, як справді розпочнеться наступний цикл циклу.

## 7.11. Оператор `import`

    import_stmt:     ["lazy"] "import" module ["as" identifier] ("," module ["as" identifier])*
                     | ["lazy"] "from" relative_module "import" identifier ["as" identifier]
                     ("," identifier ["as" identifier])*
                     | ["lazy"] "from" relative_module "import" "(" identifier ["as" identifier]
                     ("," identifier ["as" identifier])* [","] ")"
                     | "from" relative_module "import" "*"
    module:          (identifier ".")* identifier
    relative_module: "."* module | "."+

Базовий оператор імпорту (без пропозиції `from`) виконується у два кроки:

1. знайти модуль, завантаживши та ініціалізувавши його, якщо необхідно

2. define a name or names in the current namespace for the scope where the `import` statement occurs, just as an assignment statement would (including `global` and `nonlocal` semantics).

Якщо оператор містить кілька пунктів (розділених комами), два кроки виконуються окремо для кожного пункту, так само, як якщо б пункти були розділені на окремі оператори імпорту.

The details of the first step, finding and loading modules, are described in greater detail in the section on the import system, which also describes the various types of packages and modules that can be imported, as well as all the hooks that can be used to customize the import system. Note that failures in this step may indicate either that the module could not be located, or that an error occurred while initializing the module, which includes execution of the module’s code.

Якщо запитуваний модуль успішно отримано, він стане доступним у локальному просторі імен одним із трьох способів:

- Якщо ім’я модуля супроводжується `as`, тоді ім’я після `as` прив’язується безпосередньо до імпортованого модуля.

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

- Якщо імпортований модуль не є модулем верхнього рівня, тоді ім’я пакета верхнього рівня, який містить модуль, прив’язується до локального простору імен як посилання на пакет верхнього рівня. Доступ до імпортованого модуля потрібно отримати, використовуючи його повне кваліфіковане ім’я, а не безпосередньо

Форма `from` використовує дещо складніший процес:

1. знайти модуль, указаний у пункті `from`, завантажуючи та ініціалізуючи його, якщо необхідно;

2. для кожного з ідентифікаторів, указаних у пунктах `import`:

   1. перевірте, чи імпортований модуль має атрибут із таким іменем

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

   3. якщо атрибут не знайдено, виникає `ImportError`.

   4. otherwise, a reference to that value is stored in the current namespace, using the name in the `as` clause if it is present, otherwise using the attribute name

Приклади:

    import foo                 # foo imported and bound locally
    import foo.bar.baz         # foo, foo.bar, and foo.bar.baz imported, foo bound locally
    import foo.bar.baz as fbb  # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as fbb
    from foo.bar import baz    # foo, foo.bar, and foo.bar.baz imported, foo.bar.baz bound as baz
    from foo import attr       # foo imported and foo.attr bound as attr

Якщо список ідентифікаторів замінено зірочкою (`'*'`), усі загальнодоступні імена, визначені в модулі, прив’язуються до локального простору імен для області, де виникає оператор `import`.

The public names defined by a module are determined by checking the module’s namespace for a variable named `__all__`; if defined, it must be a sequence of strings which are names defined or imported by that module. Names containing non-ASCII characters must be in the normalization form NFKC; see Non-ASCII characters in names for details. The names given in `__all__` are all considered public and are required to exist. If `__all__` is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character (`'_'`). `__all__` should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).

Форма імпорту із символом підстановки — `з імпорту модуля *` — дозволена лише на рівні модуля. Спроба використати його у визначеннях класу чи функції викличе `SyntaxError`.

Визначаючи, який модуль імпортувати, не потрібно вказувати абсолютну назву модуля. Коли модуль або пакунок міститься в іншому пакунку, можна виконати відносний імпорт у той самий верхній пакунок, не вказуючи назву пакунка. Використовуючи крапки на початку у вказаному модулі чи пакеті після `from`, ви можете вказати, наскільки високо потрібно перейти вгору по поточній ієрархії пакету, не вказуючи точні назви. Одна крапка на початку означає поточний пакет, у якому існує модуль, що виконує імпорт. Дві крапки означають підвищення на один рівень пакета. Три крапки — це два рівні вище тощо. Отже, якщо ви виконаєте `з . імпортуйте mod` з модуля в пакеті `pkg`, тоді ви імпортуєте `pkg.mod`. Якщо ви виконаєте `from ..subpkg2 import mod` з `pkg.subpkg1`, ви імпортуєте `pkg.subpkg2.mod`. Специфікація відносного імпорту міститься в розділі Відносний імпорт пакетів.

`importlib.import_module()` надається для підтримки програм, які динамічно визначають модулі для завантаження.

Викликає подію аудиту `import` з аргументами `module`, `filename`, `sys.path`, `sys.meta_path`, `sys.path_hooks`.

### 7.11.1. Lazy imports

The `lazy` keyword is a soft keyword that only has special meaning when it appears immediately before an `import` or `from` statement. When an import statement is preceded by the `lazy` keyword, the import becomes lazy: the module is not loaded immediately at the import statement. Instead, a lazy proxy object is created and bound to the name. The actual module is loaded on first use of that name.

Lazy imports are only permitted at module scope. Using `lazy` inside a function, class body, or `try`/`except`/`finally` block raises a `SyntaxError`. Star imports cannot be lazy (`lazy from module import *` is a syntax error), and future statements cannot be lazy.

When using `lazy from ... import`, each imported name is bound to a lazy proxy object. The first access to any of these names triggers loading of the entire module and resolves only that specific name to its actual value. Other names remain as lazy proxies until they are accessed.

Example:

    lazy import json
    import sys

    print('json' in sys.modules)  # False - json module not yet loaded

    # First use triggers loading
    result = json.dumps({"hello": "world"})

    print('json' in sys.modules)  # True - now loaded

If an error occurs during module loading (such as `ImportError` or `SyntaxError`), it is raised at the point where the lazy import is first used, not at the import statement itself.

See PEP 810 for the full specification of lazy imports.

Added in version 3.15.

#### 7.11.1.1. Compatibility via `__lazy_modules__`

As an alternative to using the `lazy` keyword, a module can opt into lazy loading for specific imports by defining a module-level `__lazy_modules__` variable. When present, it must be a container of fully qualified module name strings. Any regular (non-`lazy`) `import` statement at module scope whose target appears in `__lazy_modules__` is treated as a lazy import, exactly as if the `lazy` keyword had been used.

This provides a way to enable lazy loading for specific dependencies without changing individual `import` statements. This is useful when supporting Python versions older than 3.15 while using lazy imports in 3.15+:

    __lazy_modules__ = ["json", "pathlib"]

    import json     # loaded lazily (name is in __lazy_modules__)
    import os       # loaded eagerly (name not in __lazy_modules__)

    import pathlib  # loaded lazily

Relative imports are resolved to their absolute name before the lookup, so `__lazy_modules__` must always contain fully qualified module names.

For `from`-style imports, the relevant name is the module following `from`, not the names of its members:

    # In mypackage/mymodule.py
    __lazy_modules__ = ["mypackage", "mypackage.sub.utils"]

    from . import helper         # loaded lazily: . resolves to mypackage
    from .sub.utils import func  # loaded lazily: .sub.utils resolves to mypackage.sub.utils
    import json                  # loaded eagerly (not in __lazy_modules__)

Imports inside functions, class bodies, or `try`/`except`/`finally` blocks are always eager, regardless of `__lazy_modules__`.

Added in version 3.15.

### 7.11.2. Майбутні заяви

future statement — це вказівка компілятору про те, що певний модуль має бути скомпільовано з використанням синтаксису чи семантики, які будуть доступні у визначеному майбутньому випуску Python, де ця функція стане стандартною.

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

    future_stmt: "from" "__future__" "import" feature ["as" identifier]
                 ("," feature ["as" identifier])*
                 | "from" "__future__" "import" "(" feature ["as" identifier]
                 ("," feature ["as" identifier])* [","] ")"
    feature:     identifier

У верхній частині модуля має бути майбутня заява. Єдині рядки, які можуть відображатися перед майбутнім оператором:

- рядок документації модуля (якщо є),

- коментарі,

- порожні рядки та

- інші майбутні заяви.

Єдина функція, яка вимагає використання оператора future, це `анотації` (див. PEP 563).

Python 3 усе ще розпізнає всі історичні функції, увімкнені оператором future. Список включає `absolute_import`, `division`, `generators`, `generator_stop`, `unicode_literals`, `print_function`, `nested_scopes` і `with_statement`. Усі вони зайві, оскільки завжди ввімкнені та зберігаються лише для зворотної сумісності.

Майбутній оператор розпізнається та обробляється спеціально під час компіляції: зміни в семантиці основних конструкцій часто впроваджуються шляхом генерації іншого коду. Може навіть статися так, що нова функція вводить новий несумісний синтаксис (наприклад, нове зарезервоване слово), і в цьому випадку компілятору може знадобитися розібрати модуль по-іншому. Такі рішення не можуть бути відкладені до часу виконання.

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

Пряма семантика часу виконання така ж, як і для будь-якого оператора імпорту: є стандартний модуль `__future__`, описаний пізніше, і його буде імпортовано звичайним способом під час виконання оператора майбутнього.

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

Зауважте, що в заяві немає нічого особливого:

    import __future__ [as name]

Це не заява про майбутнє; це звичайний оператор імпорту без спеціальних семантичних або синтаксичних обмежень.

Code compiled by calls to the built-in functions `exec()` and `compile()` that occur in a module `M` containing a future statement will, by default, use the new syntax or semantics associated with the future statement. This can be controlled by optional arguments to `compile()` — see the documentation of that function for details.

Майбутній оператор, набраний у підказці інтерактивного перекладача, матиме чинність до кінця сеансу перекладача. Якщо інтерпретатор запускається з параметром `-i`, йому передається ім’я сценарію для виконання, і сценарій містить майбутній оператор, він діятиме в інтерактивному сеансі, розпочатому після виконання сценарію.

Дивись також

PEP 236 - Назад у __future__

  Оригінальна пропозиція щодо механізму __future__.

## 7.12. Оператор `global`

    global_stmt: "global" identifier ("," identifier)*

The `global` statement causes the listed identifiers to be interpreted as globals. It would be impossible to assign to a global variable without `global`, although free variables may refer to globals without being declared global.

The `global` statement applies to the entire current scope (module, function body or class definition). A `SyntaxError` is raised if a variable is used or assigned to prior to its global declaration in the scope.

At the module level, all variables are global, so a `global` statement has no effect. However, variables must still not be used or assigned to prior to their `global` declaration. This requirement is relaxed in the interactive prompt (REPL).

Примітка програміста: `global` — це директива для аналізатора. Це стосується лише коду, аналізованого одночасно з оператором `global`. Зокрема, оператор `global`, що міститься в рядку або об’єкті коду, що надається вбудованій функції `exec()`, не впливає на блок коду, що містить виклик функції, і код, що міститься в таких на рядок не впливають оператори `global` у коді, що містить виклик функції. Те саме стосується функцій `eval()` і `compile()`.

## 7.13. Оператор `nonlocal`

    nonlocal_stmt: "nonlocal" identifier ("," identifier)*

When the definition of a function or class is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local scopes of the enclosing functions. The `nonlocal` statement causes the listed identifiers to refer to names previously bound in nonlocal scopes. It allows encapsulated code to rebind such nonlocal identifiers. If a name is bound in more than one nonlocal scope, the nearest binding is used. If a name is not bound in any nonlocal scope, or if there is no nonlocal scope, a `SyntaxError` is raised.

The `nonlocal` statement applies to the entire scope of a function or class body. A `SyntaxError` is raised if a variable is used or assigned to prior to its nonlocal declaration in the scope.

Дивись також

PEP 3104 - Доступ до імен у зовнішніх областях

  Специфікація оператора `nonlocal`.

Programmer’s note: `nonlocal` is a directive to the parser and applies only to code parsed along with it. See the note for the `global` statement.

## 7.14. The `type` statement

    type_stmt: 'type' identifier [type_params] "=" expression

The `type` statement declares a type alias, which is an instance of `typing.TypeAliasType`.

For example, the following statement creates a type alias:

    type Point = tuple[float, float]

This code is roughly equivalent to:

    annotation-def VALUE_OF_Point():
        return tuple[float, float]
    Point = typing.TypeAliasType("Point", VALUE_OF_Point())

`annotation-def` indicates an annotation scope, which behaves mostly like a function, but with several small differences.

The value of the type alias is evaluated in the annotation scope. It is not evaluated when the type alias is created, but only when the value is accessed through the type alias’s `__value__` attribute (see Lazy evaluation). This allows the type alias to refer to names that are not yet defined.

Type aliases may be made generic by adding a type parameter list after the name. See Generic type aliases for more.

`type` is a soft keyword.

Added in version 3.12.

Дивись також

PEP 695 - Type Parameter Syntax

  Introduced the `type` statement and syntax for generic classes and functions.