Classes
Dataclasses
Section titled “Dataclasses”@dataclass makes a class from its fields, with a constructor, structural equality and a readable display:
@dataclassclass Point: x: float y: float
def distance_to(self, other: Point) -> float: return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5
let p = Point(0, 0)let q = Point(x=3, y=4)print(q, p.distance_to(q), p == Point(0, 0))Point(x=3.0, y=4.0) 5.0 True@dataclass(frozen=True) makes the fields read-only, and @dataclass(order=True) adds < and the other comparisons.
Plain classes
Section titled “Plain classes”A plain class declares its fields and sets them in __init__. Every field must be set before __init__ returns, unless it has a default:
class Account: owner: str balance: int = 0
def __init__(self, owner: str): self.owner = owner
def deposit(self, amount: int): if amount <= 0: raise ValueError("deposit must be positive") self.balance += amount
let a = Account("ada")a.deposit(50)print(a.owner, a.balance)ada 50Plain classes compare by identity, as in Python.
Inheritance
Section titled “Inheritance”A class derives from one base class. An overriding method is marked @override, so renaming a base method can’t silently leave an override behind:
class Animal: name: str
def __init__(self, name: str): self.name = name
def speak(self) -> str: return "..."
class Dog(Animal): @override def speak(self) -> str: return f"{self.name} says woof"
class Cat(Animal): @override def speak(self) -> str: return f"{self.name} says meow"
let pets = [Dog("rex"), Cat("tom")]for pet in pets: print(pet.speak()) if isinstance(pet, Dog): print(" good dog")rex says woof good dogtom says meow[Dog("rex"), Cat("tom")] is a list[Animal], the elements’ nearest common base. isinstance narrows a value to the class it tests, and super().method(…) calls the base class’s method. @abstractmethod marks a method subclasses must define, and @final a class or method that can’t be extended.
Properties, static and class methods
Section titled “Properties, static and class methods”class Temperature: celsius: float
def __init__(self, celsius: float): self.celsius = celsius
@property def fahrenheit(self) -> float: return self.celsius * 9 / 5 + 32
@fahrenheit.setter def fahrenheit(self, value: float): self.celsius = (value - 32) * 5 / 9
@staticmethod def freezing() -> Temperature: return Temperature(0)
let t = Temperature.freezing()t.fahrenheit = 212print(t.celsius, t.fahrenheit)100.0 212.0Special methods
Section titled “Special methods”Python’s special methods give a class operators, display, hashing and more: __str__, __repr__, __eq__, __hash__, __lt__ and the other comparisons, __add__ and the other arithmetic operators, __len__, __getitem__, __setitem__, __contains__, __iter__, __call__, and __enter__/__exit__ for with.
@dataclass(frozen=True)class Money: cents: int
def __add__(self, other: Money) -> Money: return Money(self.cents + other.cents)
def __lt__(self, other: Money) -> bool: return self.cents < other.cents
def __str__(self) -> str: return f"${self.cents // 100}.{self.cents % 100:02}"
let prices = [Money(250), Money(99), Money(1000)]print(prices[0] + prices[1], min(prices), sorted(prices)[-1])$3.49 $0.99 $10.00Each special method’s signature is checked: a __lt__ that doesn’t return bool, say, is an error.
Next: Enums and match.
© 2026 Discover Edge, LLC · Taipan is released under the MIT License.