MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Modulul dataclass. Clasele de date

Modulul dataclasses oferă decoratorul @dataclass, care permite crearea claselor de date (data classes), reducând astfel semnificativ codul boilerplate al claselor. De regulă, aceste clase sunt destinate stocării unor stări sau date și nu necesită comportamente complexe sub forma funcțiilor.

Exemplu simplu:

class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age

tom = Person("Tom", 38)
print(f"Name: {tom.name}  Age: {tom.age}")  # Name: Tom  Age: 38

Aici am definit clasa Person, care are două atribute în constructor: name și age. Apoi am creat un obiect al acestei clase și am afișat valorile atributelor sale.

Acum să modificăm această programă, transformând clasa Person într-o clasă de date:

from dataclasses import dataclass

@dataclass
class Person:
   name: str
   age: int

tom = Person("Tom", 38)
print(f"Name: {tom.name}  Age: {tom.age}")  # Name: Tom  Age: 38

Pentru a crea o clasă de date, importăm decoratorul @dataclass din modulul dataclasses și îl aplicăm clasei Person. În acest caz, nu mai trebuie să specificăm explicit constructorul __init__. Doar indicăm atributele, iar Python va genera automat constructorul, permițându-ne să transmitem valori pentru atributele obiectului.

Astfel, am simplificat definirea clasei. Dar funcționalitatea decoratorului @dataclass nu se limitează la generarea metodei __init__. În realitate, clasa de date:

@dataclass
class Person:
   name: str
   age: int

este echivalentă cu următoarea:

class Person:
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __repr__(self):
       return f"Person(name={self.name!r}, age={self.age!r})"

   def __eq__(self, other):
       if other.__class__ is self.__class__:
           return (self.name, self.age) == (other.name, other.age)
       return NotImplemented

Pe lângă funcția __init__, sunt generate automat și funcțiile __repr__() pentru a oferi o reprezentare textuală și __eq__() pentru a compara două obiecte. Exemplu de utilizare a acestor funcții:

from dataclasses import dataclass

@dataclass
class Person:
   name: str
   age: int

tom = Person("Tom", 38)
bob = Person("Bob", 42)
tomas = Person("Tom", 38)

print(tom == tomas)  # True
print(tom == bob)    # False
print(tom)           # Person(name="Tom", age=38)

Parametrii decoratorului @dataclass

Cu ajutorul parametrilor, decoratorul @dataclass poate genera cod suplimentar și permite personalizarea generării codului:

def dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False,
             unsafe_hash=False, frozen=False, match_args=True,
             kw_only=False, slots=False)

Parametrii principali:

  • init: dacă este True, se generează funcția __init__(). Implicit este True
  • repr: dacă este True, se generează funcția __repr__(), care returnează o reprezentare textuală a obiectului. Implicit este True
  • eq: dacă este True, se generează funcția __eq__(), care compară două obiecte. Implicit este True
  • order: dacă este True, se generează funcțiile __lt__ (operația <), __le__ (<=), __gt__ (>), __ge__ (>=), care sunt utilizate pentru ordonarea obiectelor. Implicit este False
  • unsafe_hash: dacă este True, se generează funcția __hash__(), care returnează hash-ul obiectului. Implicit este False

Funcțiile generate implicit pot fi suprascrise.

Exemplu de utilizare a parametrilor:

from dataclasses import dataclass

@dataclass(unsafe_hash=True, order=True)
class Person:
   name: str
   age: int

   def __repr__(self):
       return f"Person. Name: {self.name}  Age: {self.age}"

tom = Person("Tom", 38)
print(tom.__hash__())  # -421667297069596717
print(tom)             # Person. Name: Tom  Age: 38

În acest caz, activăm generarea hash-ului și a funcțiilor de ordonare, precum și suprascriem explicit funcția __repr__ pentru a crea o reprezentare textuală personalizată a obiectului.

Valori implicite

Dacă este necesar, atributelor li se pot atribui valori implicite în cazul în care constructorul nu primește valori pentru acestea:

from dataclasses import dataclass

@dataclass
class Person:
   name: str
   age: int = 18

tom = Person("Tom", 38)
print(tom)  # Person(name="Tom", age=38)

bob = Person("Bob")
print(bob)  # Person(name="Bob", age=18)

Adăugarea de funcționalitate suplimentară

Deși clasele de date sunt destinate în principal stocării de date, ele pot include și metode suplimentare pentru a adăuga funcționalitate:

from dataclasses import dataclass

@dataclass
class Person:
   name: str
   age: int

   def say_hello(self):
       print(f"{self.name} says hello")

tom = Person("Tom", 38)
tom.say_hello()  # Tom says hello
← Lecția anterioară Lecția următoare →