Instrukcje przypisania używane są do wiązania wartości z nazwami oraz do modyfikowania atrybutów lub elementów obiektów zmiennych.
assignment_stmt |
::= | (target_list "=")+ expression_list |
target_list |
::= | target ("," target)* [","] |
target |
::= | identifier |
| "(" target_list ")" | ||
| "[" target_list "]" | ||
| attributeref | ||
| subscription | ||
| slicing |
(definicje składni ostatnich trzech symboli znajdują się w sekcji 5.3.)
Instrukcja przypisania wartościuje listę wyrażeń (pamiętajmy, że może to być pojedyncze wyrażenie lub lista wyrażeń rozdzielonych przecinkami, gdzie drugi przypadek reprezentuje krotkę) i przypisuje każdemu z elementów z listy docelowej pojedynczy obiekt wynikowy, w kolejności od lewej do prawej.
Przypisanie jest definiowane rekurencyjnie, w zależności od postaci celu (listy docelowej). Jeśli cel jest częścią obiektu zmiennego (odwołaniem do atrybutu, odwołaniem do indeksu lub wykrojeniem), ostateczne przypisanie z uprzednim sprawdzeniem poprawności i ewentualnym wygenerowaniem wyjątku w razie operacji niepoprawnej w całości wykonuje ów zmienny obiekt. Reguły, którym podlegają różne typy i używane w różnych wypadkach wyjątki podawane są z definicjami typów obiektów (patrz sekcja 3.2).
Przypisanie obiektu do listy docelowej jest zdefiniowane rekurencyjnie w sposób przedstawiony poniżej.
Przypisanie obiektu do pojedynczego celu jest zdefiniowane rekurencyjnie w sposób przedstawiony poniżej.
Jeśli nazwa jest już powiązana, następuje jej powiązanie na nowo. Może to spowodować spadek do zera wartości licznika odwołań do poprzednio dowiązanego obiektu, a co za tym idzie, wywołanie jego destruktora (jeśli obiekt go posiada) i zwolnienie zajmowanej przez niego pamięci.
Jeśli główne wyrażenie jest zmienną sekwencją (np. listą), wartością indeksu musi być zwykła liczba całkowita. W przypadku, gdy liczba jest ujemna, jest do niej dodawana długość sekwencji. Wynikowa wartość musi być liczbą nieujemną, mniejszą od długości sekwencji. Do sekwencji należy wówczas przypisanie przypisywanego obiektu elementowi o podanym indeksie. Jeśli wartość indeksu wykracza poza określony zakres, generowany jest wyjątek IndexError (przypisanie do indeksowanego elementu sekwencji nie może służyć dodawaniu do niej elementów).
Jeśli główne wyrażenie jest obiektem odwzorowawczym (np. słownikiem), wartość indeksu musi być typu zgodnego z typem klucza odwzorowania. Do słownika należy wówczas utworzenie pary klucz/dane, która odwzorowuje wartość indeksu na przypisywany obiekt. Nowy element może albo zastąpić istniejącą parę klucz/wartość (jeśli klucz o tej samej wartości już istnieje), albo zostać wstawiony jako nowy (jeśli w odwzorowaniu nie ma pary o tym kluczu).
(W bieżącej implementacji Pythona przyjęto dla celów taką samą składnię, jak dla wyrażeń, a zapis niepoprawny składniowo jest odrzucany na etapie generowania kodu, co skutkuje mniej szczegółowymi komunikatami na temat błędów.)
UWAGA: Choć z definicji przypisania wynika, że pokrywanie się nazw po lewej i prawej stronie jest "bezpieczne" (np. "a, b = b, a"zamienia wartości dwóch zmiennych), jednak pokrywanie się nazw wewnątrz zestawu zmiennych, którym przypisujemy wartości, już bezpieczne nie jest. Na przykład, poniższy fragment programu spowoduje wypisanie wartości "[0, 2]":
x = [0, 1] i = 0 i, x[i] = 1, 2 print x
Modyfikująca instrukcja przypisania jest połączeniem w jednej instrukcji operacji dwuargumentowej oraz instrukcji przypisania:
augmented_assignment_stmt |
::= | target augop expression_list |
augop |
::= | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" |
| "»=" | "«=" | "&=" | "^=" | "|=" |
(definicje składni ostatnich trzech symboli znajdują się w sekcji 5.3.)
Modyfikująca instrukcja przypisania wartościuje cel (który, w odróżnieniu od zwykłych instrukcji przypisania, musi być celem pojedynczym) oraz listę wyrażeń, następnie zaś wykonuje operację dwuargumentową określoną dla danego rodzaju przypisania i przypisuje wynik do celu. Cel wartościowany jest tylko raz.
Modyfikującą instrukcję przypisania postaci x += 1 można zapisać
jako x = x + 1, otrzymując podobny, lecz niezupełnie taki sam efekt.
Przy odmianie z przypisaniem modyfikującym x wartościowane jest
bowiem tylko raz. Dodatkowo, jeśli jest to możliwe, cała operacja jest
przeprowadzana w miejscu, co oznacza, że zamiast tworzenia nowego
obiektu i przypisania go do celu może zostać od razu zmodyfikowany obiekt
docelowy.
Za wyjątkiem przypisań do krotek i wielu celów w jednej instrukcji, przypisanie wykonane przez instrukcję modyfikującą jest obsługiwane w ten sam sposób, co zwykłe przypisanie. Również za wyjątkiem możliwego wykonania operacji w miejscu operacje dwuargumentowe wykonywane przez te przypisania są takie same, jak przy samodzielnym użyciu operatorów dwuargumentowych.
W przypadku celów, które są odwołaniami do atrybutów, początkowa wartość jest uzyskiwana poprzez wywołanie getattr(), zaś wynik operacji jest przypisywany poprzez wywołanie setattr(). Należy zwrócić uwagę, że te dwie metody niekoniecznie muszą się odwoływać do tej samej zmiennej. Nawet, jeśli getattr() odwołuje się do zmiennej klasy, setattr() zapisuje zmienną instancji. Na przykład:
class A:
x = 3 # zmienna klasy
a = A()
a.x += 1 # zapisuje a.x o wartości 4, pozostawiając A.x jako 3
Zajrzyj do Informacji na temat tej publikacji... aby pomóc w jej rozwoju.