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

Оновлено: 24.04.2023

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

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

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

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

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

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

Якщо цільовий список є одним цільовим об’єктом без кінцевої коми, необов’язково в дужках, об’єкт призначається цій цільовій цілі. ще: Якщо цільовий список містить одну ціль із префіксом зірочки, це називається ціль із зірочкою: об’єкт має бути ітерованим із принаймні такою кількістю елементів, скільки цілей у списку цілей, мінус один. Перші елементи 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(). Якщо метою є підписка: обчислюється основний вираз у посиланні. Він повинен давати або об’єкт змінної послідовності (наприклад, список), або об’єкт відображення (наприклад, словник). Далі обчислюється нижній індекс. Якщо основний об’єкт є змінним об’єктом послідовності (наприклад, список), нижній індекс повинен давати ціле число. Якщо він від’ємний, до нього додається довжина послідовності. Отримане значення має бути невід’ємним цілим числом, меншим за довжину послідовності, і послідовності пропонується призначити призначений об’єкт своєму елементу з цим індексом. Якщо індекс виходить за межі діапазону, виникає IndexError (присвоєння послідовності з індексом не може додавати нові елементи до списку). Якщо основним є об’єкт відображення (наприклад, словник), нижній індекс повинен мати тип, сумісний із типом ключа відображення, а потім відображення запитується створити пару ключ/дані, яка відображає підіндекс у призначений об’єкт. Це може або замінити наявну пару ключ/значення тим самим значенням ключа, або вставити нову пару ключ/значення (якщо ключа з таким самим значенням не існує). Для об’єктів, визначених користувачем, метод __setitem__() викликається з відповідними аргументами. Якщо метою є нарізка: обчислюється основний вираз у посиланні. Він повинен давати змінний об’єкт послідовності (наприклад, список). Призначений об’єкт має бути об’єктом послідовності того самого типу. Далі обчислюються вирази нижньої та верхньої межі, якщо вони присутні; за замовчуванням нуль і довжина послідовності. Межі повинні обчислюватися як цілі числа. Якщо будь-яка межа негативна, до неї додається довжина послідовності. Отримані межі обрізаються між нулем і довжиною послідовності включно. Нарешті, об’єкту послідовності пропонується замінити зріз елементами призначеної послідовності. Довжина зрізу може відрізнятися від довжини призначеної послідовності, таким чином змінюючи довжину цільової послідовності, якщо це дозволяє цільова послідовність.

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

Хоча визначення присвоєння передбачає, що збіги між лівою та правою сторонами є «одночасними» (наприклад, 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)