Co to jest __dict__? Jest to słownik właściwości danego obiektu np.:
from dataclasses import dataclass
@dataclass()
class User:
name: str
age: strJak widzisz, klasa User zawiera dwie właściwości, name oraz age. Teraz stwórzmy nowy obiekt tej klasy.
user = User('John', 25)Aby odczytać wartości tych właściwości należało by zrobić np tak:
print(user.name)
#JohnZamiast tego możemy wykorzystać słownik który tworzy się automatycznie w momencie tworzenia nowego obiektu klasy.
print(user.__dict__['name'])
#JohnNo i po co mi to, nie dość że zapis dłuższy to jeszcze trochę słabo wygląda, może i tak, ale odczytywanie wartości właściwości to tylko wierzchołek, idźmy dalej. Może wylistujmy sobie wszystkie wartości:
print(user.__dict__.items())
#dict_items([('name', 'John'), ('age', 25)])Wrzućmy to w pętlę
for key, value in user.__dict__.items():
print(f"{key} = {value}")
'''
name = John
age = 25
'''A może skonwertujemy te wartości na JSON?
Zaimportujmy bibliotekę json.
from dataclasses import dataclass
import json
@dataclass
class User:
name: str
age: str
user = User('John', 25)
print(json.dumps(user.__dict__))
#{"name": "John", "age": 25}Ciągle jeszcze mało, może zróbmy klonowanie obiektu.
user = User('John', 25)
user2 = User(**user.__dict__)
print(user2.name)
#JohnJak widzisz, nie muszę wprowadzać każdej właściwości osobno, wrzucam cały słownik.
A może by tak spróbować zaktualizować kilka właściwości w obiekcie?
update = {"age" : 30, "name" : "Tom"}
user.__dict__.update(update)
print(user.__dict__)
#{'name': 'Tom', 'age': 30}Kojarzysz parametr frozen dekoratora @dataclass? Parametr ten określa obiekt klasy jako niemożliwy do zmodyfikowania. Co to znaczy? Tylko to, że nie będziesz miał możliwości zmiany wartości właściwości obiektu.
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
age: str
user = User('John', 25)
user.name = "Tom"Takie działanie spowoduje wystąpienie błędu
dataclasses.FrozenInstanceError: cannot assign to field 'name'Dzięki __dict__ możemy obejść tą blokadę
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
age: str
user = User('John', 25)
user.__dict__['name'] = "Tom";
print(user.name)
#TomTaką operację można przeprowadzić również za pomocą object.__setattr__
user = User('John', 25)
object.__setattr__(user, 'name', "Tom")
print(user.name)
#Tom__dict__ pozwala nam również na wygnerowanie dynamicznych właściwości klasy
fields = ["x", "y", "z"]
@dataclass
class Point:
def __init__(self, values):
self.__dict__.update(dict(zip(fields, values)))
p = Point([1,2,3])
print(p.__dict__)Może ten fragment wydaje Ci sie niejasny?
self.__dict__.update(dict(zip(fields, values)))funkcja zip() łączy dwie (lub więcej) listy element po elemencie, w naszym przypadku połączy listę fields oraz wartości przekazane w konstruktorze klasy Point.
funkcja dict() zamienia te połączone listy w słownik
self.__dict__.update() aktualizuje właściwości obiektu.
Efektem działania tego kodu jest to:
{'x': 1, 'y': 2, 'z': 3}Możemy również szybko modyfikować __repr__ i __str__
class SomeClass:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
return f"{self.__class__.__name__} debug: ({self.__dict__})"
some_object = SomeClass(name="Tom", age="30")
print(some_object)
#SomeClass debug: ({'name': 'Tom', 'age': '30'})dodajmy do tego metode __str__
def __str__(self):
return f"{self.__dict__['name']} ma {self.__dict__['age']} lat"Po uruchomieniu kodu w konsoli zobaczymy teraz
Tom ma 30 lat
Dodaj komentarz