1. Dataclass

1.1. Old style classes

class Astronaut:
    def __init__(self, first_name, last_name, agency='NASA'):
        self.first_name = first_name
        self.last_name = last_name
        self.agency = agency

1.2. New style dataclasses

from dataclasses import dataclass


@dataclass
class Astronaut:
    first_name: str
    last_name: str
    agency: str = 'NASA'

1.3. __init__ vs. __post_init__

from dataclasses import dataclass


@dataclass
class Kelvin:
    value: float = 0.0

    def __post_init__(self):
        if self.value < 0.0:
            raise ValueError('Temperature must be greater than 0')


temp = Kelvin(-300)

1.4. More advanced options

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
Tab. 1.1. More advanced options
Option Default Description (if True)
init True Generate __init__ method
repr True Generate __repr__ method
eq True Generate __eq__ method
order False Generate __lt__, __le__, __gt__, and __ge__ methods
unsafe_hash False if False: the __hash__ method is generated according to how eq and frozen are set
frozen False if True: assigning to fields will generate an exception

1.5. Under the hood

1.5.1. Write

from dataclasses import dataclass

@dataclass
class InventoryItem:
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

1.5.2. Dataclass will add

class InventoryItem:

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

    def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0) -> None:
        self.name = name
        self.unit_price = unit_price
        self.quantity_on_hand = quantity_on_hand

    def __repr__(self):
        return f'InventoryItem(name={self.name!r}, unit_price={self.unit_price!r}, quantity_on_hand={self.quantity_on_hand!r})'

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

    def __ne__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.unit_price, self.quantity_on_hand) != (other.name, other.unit_price, other.quantity_on_hand)
        return NotImplemented

    def __lt__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.unit_price, self.quantity_on_hand) < (other.name, other.unit_price, other.quantity_on_hand)
        return NotImplemented

    def __le__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.unit_price, self.quantity_on_hand) <= (other.name, other.unit_price, other.quantity_on_hand)
        return NotImplemented

    def __gt__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.unit_price, self.quantity_on_hand) > (other.name, other.unit_price, other.quantity_on_hand)
        return NotImplemented

    def __ge__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.unit_price, self.quantity_on_hand) >= (other.name, other.unit_price, other.quantity_on_hand)
        return NotImplemented

1.6. Assignments

1.6.1. Address Book (dataclass)

  1. Zmień kod książki adresowej z listingu Code Listing 1.1. na wykorzystujący mechanizm dataclass
Code Listing 1.1. Easy object implementation of Address Book
class AddressBook:
    def __init__(self, contacts=()):
        self.contacts = contacts


class Address:
    def __init__(self, street=None, city=None):
        self.street = street
        self.city = city


class Contact:
    def __init__(self, first_name, last_name, addresses=()):
        self.first_name = first_name
        self.last_name = last_name
        self.address = addresses


AddressBook([
    Contact(first_name='José', last_name='Jiménez'),
    Contact(first_name='Иван', last_name='Иванович', addresses=[]),
    Contact(first_name='Matt', last_name='Kowalski', addresses=[
        Address(street='2101 E NASA Pkwy', city='Houston'),
        Address(city='Kennedy Space Center'),
        Address(street='4800 Oak Grove Dr', city='Pasadena'),
        Address(street='2825 E Ave P', city='Palmdale'),
    ])
])

About:
  • Filename: oop_dataclass_addressbook.py
  • Lines of code to write: 15 lines
  • Estimated time of completion: 10 min