Rozdział 14 · Tworzenie rzeczywistych obiektów

Powszechna pułapka atrybutów zmiennych

One lista „for two”

Kiedy „wspólny atrybut” zamienia się w błąd

Atrybut klasy o NIEZMIENNEJ wartości (liczba, łańcuch znaków) jest bezpieczny – przypisanie przez obiekt po prostu tworzy nowy atrybut instancji (sekcja 14.7). Ale atrybut klasy z ZMIENNE znaczenie — lista lub słownik — jest ułożone inaczej: jeśli nie jest PRZYDZIEL i ZMIANA miejsca (.append(), [key] = ...), to wpłynie na obiekt klasy, którego używają WSZYSTKIE egzemplarze naraz.

Debug Lab 3: wspólny zmienny lista jako atrybut klasy
obshchaya_korzina.py
class Korzina:
    tovary = []          # atrybut KLASY – jeden lista dla wszystkich koszyków!

    def dobavit(self, tovar):
        self.tovary.append(tovar)   #. append() ZMIENIA lista NA MIEJSCU

k1 = Korzina()
k2 = Korzina()
k1.dobavit(„Chleb”)
print(k2.tovary)
>>> print(k2.tovary)
['Хлеб']
Co widać na ekranie

k2 nigdy nie dzwonił dobavit(), ale „Chleb” jest już w jego koszyku! Powód: self.tovary.append(...) nie tworzy nowego lista — MODYFIKUJE istniejący, a ten lista jest jedynym, który odziedziczony są przez oba obiekty z Korzina.

Poprawiony kod
svoya_korzina.py
class Korzina:
    def __init__(self):
        self.tovary = []    atrybut # INSTANCJA — każdy kartridż ma własny lista

    def dobavit(self, tovar):
        self.tovary.append(tovar)

k1 = Korzina()
k2 = Korzina()
k1.dobavit(„Chleb”)
print(k2.tovary)   # [] - pusty, jak powinno być
k1.tovaryk2.tovary[] - Ogólnelista klasie...
Bez self.tovary = [] w __init__ oba odniesienia prowadzą do TEJ samej listy
Zasada: Wartości modyfikowalne są tylko w __init__
Jeśli atrybut potrzebuje wartości list, dict lub set – stwórz to w środku __init__ przez self.имя = [], nie w treści klasy. To ta sama zasada co „pułapka zmiennej wartości domyślnej”
Praktyka: znajdujemy wspólny zmienny atrybut
interaktywny laptop bezpośrednio w przeglądarce – Python 3.14 przez Pyodide, bez instalacji
Otwórz praktykę →