AI Hints
Home›Python Tutorial›Modern Classes and the Standard Library
Python · Lesson 19 of 49

Dataclasses, Enums and Abstract Classes

Less boilerplate, safer design.

⏱ 2 min read▶ Video at 1:01:21🎓 Free
Watch this lesson in the Python courseWatch on YouTube ↗Full Python course

Ava's Plant class has twelve lines, and most of them only store data. Every new class repeats the same init, repr and eq. Modern Python removes that boilerplate. Data classes write the boring methods for you. Enums give names to fixed choices. And abstract classes define rules that every subclass must follow.

Dataclasses, Enums and Abstract Classes
From the video: Dataclasses, Enums and Abstract Classes
  • Too much repeated boilerplate
  • Fixed choices deserve names
  • Some classes must follow rules

Dataclasses

Import dataclass, and decorate your class. You only list the fields with their types. Python then writes init, repr, and eq for you. You can give defaults, and create ordered or frozen versions. Compare it with the earlier version, and notice how much shorter it is.

dataclass1.pypython
from dataclasses import dataclass

@dataclass
class Plant:
    name: str
    price: float
    stock: int = 0

a = Plant("fern", 9.5, 12)
b = Plant("fern", 9.5, 12)
print(a)
print(a == b)
print(Plant("ivy", 7.0))
Output
Plant(name='fern', price=9.5, stock=12)
True
Plant(name='ivy', price=7.0, stock=0)

More dataclass features

With frozen equals True, instances cannot be changed, which makes them safe and hashable. The field function handles tricky defaults, like an empty list, because a plain list default would be shared. And you can add normal methods too. Dataclasses are the best way to define simple records.

dataclass2.pypython
from dataclasses import dataclass, field

@dataclass(frozen=True)
class Point:
    x: int
    y: int

@dataclass
class Basket:
    items: list = field(default_factory=list)
    def add(self, item):
        self.items.append(item)

p = Point(1, 2)
print(p)
b = Basket()
b.add("fern")
print(b)
try:
    p.x = 9
except Exception as e:
    print(type(e).__name__)
Output
Point(x=1, y=2)
Basket(items=['fern'])
FrozenInstanceError

Enums: named choices

An enum is a fixed set of named values. Instead of using the strings, paid, and shipped, which are easy to mistype, you define them once. Nobody can invent a state by accident, and your editor can autocomplete them. Each member has a name and a value.

enum1.pypython
from enum import Enum

class Status(Enum):
    NEW = 1
    PAID = 2
    SHIPPED = 3

s = Status.PAID
print(s)
print(s.name, s.value)
print(s == Status.PAID)
print([x.name for x in Status])
Output
Status.PAID
PAID 2
True
['NEW', 'PAID', 'SHIPPED']

Abstract base classes

An abstract class defines a contract. Methods marked abstract must be implemented by every subclass, and you cannot create objects from the abstract class itself. Here every Payment must have a pay method. Card and Cash each provide their own. If a subclass forgets, Python refuses to create it.

abc1.pypython
from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def pay(self, amount): ...

class Card(Payment):
    def pay(self, amount):
        return f"Card charged {amount}"

print(Card().pay(20))
try:
    Payment()
except TypeError as e:
    print("Cannot create:", "abstract" in str(e))
Output
Card charged 20
Cannot create: True

An Order dataclass

Your turn. Define a dataclass called Order, with a customer name, a total, and a paid flag, defaulting to False. Create one, and print it. Ready? Here is one solution. The decorator, three typed fields, one default, and you get a free readable print.

✍️ Exercise: An Order dataclass

Define a dataclass Order(customer: str, total: float, paid: bool = False) and print an instance.

Show hint

@dataclass and annotated fields

Show solution
order_dc.pypython
from dataclasses import dataclass

@dataclass
class Order:
    customer: str
    total: float
    paid: bool = False

print(Order("Maya", 34.5))
Output
Order(customer='Maya', total=34.5, paid=False)

Summary

Well done. Dataclasses remove boilerplate, enums name fixed choices, and abstract classes enforce a contract. That completes our tour of object oriented Python. Next, we explore the standard library, starting with dates, randomness, and clever collections.

Key takeaways
  • @dataclass writes init, repr, eq
  • Enum for fixed choices
  • ABC + @abstractmethod for contracts
Next up: The Standard Library — dates, randomness and smart collections