20
loading...
This website collects cookies to deliver better user experience
tuple
) or a Dictionary (dict
) in Python. We use them almost everywhere and every day in our lives programmers to store data.# Using Dictionary
car = {"name": "Model X", "brand": "Tesla", "price": 120_000}
# OR using Tuple
car = ("Model X", "Tesla", 120_000)
name
, brand
, and price
). As we add more fields into our car object such as manufacturer
, condition
, etc., we would need to remember our attributes' order.car.name
) to access our attributes. Plus, a deep-nested Dictionary tends to be very messy to work with.namedtuple
) from Python's built-in collections
library.from collections import namedtuple
Car = namedtuple('Car', ['name', 'brand', 'price'])
car = Car('Model X', 'Tesla', 120_000)
class
in Python to create our own custom objects with their own properties and methods.class Car:
def __init__(self, name: str, brand: str, price: int) -> None:
self.name = name
self.brand = brand
self.price = price
car1 = Car('Model X', 'Tesla', 120_000)
car2 = Car('Model X', 'Tesla', 120_000)
car1 == car2 # False. We need to write our own __eq__ method to handle this.
__init__
method. What if we needed to add a more descriptive representation of our car object to our __repr__
method? What if we need to compare two car instances of the same car object?Manufacturer
, CarDealer
, etc.?dataclasses
) providers us with an easy way to make our class objects less verbose. To simplify, Data Classes are just regular classes that help us abstract a tonne of boilerplate codes.@dataclass
:from dataclasses import dataclass
@dataclass
class Car:
name: str # Supports typing out of the box!
brand: str
price: int
car1 = Car('Model X', 'Tesla', 120_000)
car2 = Car('Model X', 'Tesla', 120_000)
car1 == car2 # True. __eq__ is generated automatically.
car2.name # Supports dot annotation!
__repr__
and __eq__
, eliminating all the duplicated code.In certain cases, we might need to customize our Data Class fields:
from dataclasses import dataclass, field
@dataclass
class Car:
name: str = field(compare=False) # To exclude this field from comparison
brand: str = field(repr=False) # To hide fields in __repr__
price: int = 120_000
condition: str = field(default='New')
To override what happens after __init__
inside our newly created Data Class, we can declare a __post_init__
method. For example, we can easily override the price of the car based on its initialized condition:
from dataclasses import dataclass, field
@dataclass
class Car:
name: str = field(compare=False)
brand: str = field(repr=False)
price: int = 120_000
condition: str = field(default='New')
def __post_init__(self):
if self.condition == "Old":
self.price -= 30_000
old_car = Car('Model X', 'Tesla', 130_000, 'Old')
# Car(name='Model X', price=100000, condition='Old')
To make our Data Class immutable, we simply have to add @dataclass(frozen=True)
as our decorator.
Another good use case of Data Class is when we need to deal with nested Dictionary. Here’s a simple example of what a Data Class could do:
# ...
from typing import List
@dataclass
class CarDealer:
cars: List[Car]
car3 = Car('Model S', 'Tesla', 89_000)
car4 = Car('Model Y', 'Tesla', 54_000)
car_dealer = CarDealer(cars=[car3, car4])
# CarDealer(cars=[Car(name='Model S', price=89000, condition='New'), Car(name='Model Y', price=54000, condition='New')])
Lastly, in case it wasn’t obvious, Data Class supports inheritance too as they indeed behave just like our good old regular class.