OOP Advanced
Dunders, classmethods, staticmethods, dataclasses, and MRO
Free tier: read the explanation here. Upgrade to Pro for Drills, Speed challenges & Mastery badges.
UpgradeKnowledge Debt detected
You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.
Explanation
Python's OOP goes well beyond basic classes. Here are the patterns you'll see in production code.
:dunder-method[A special method with double underscores that customizes how objects behave with operators and built-in functions, e.g. __init__ or __add__]s — customize how objects behave with operators and built-ins: ``python class Vector: def __init__(self, x, y): self.x, self.y = x, y def __repr__(self): return f"Vector({self.x}, {self.y})" def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __len__(self): return 2 v = Vector(1, 2) + Vector(3, 4) # Vector(4, 6)
classmethod vs staticmethod:
python class Temperature: def __init__(self, celsius): self.celsius = celsius @classmethod def from_fahrenheit(cls, f): # cls = the class itself return cls((f - 32) * 5/9) @staticmethod def is_freezing(celsius): # no cls or self — pure utility return celsius <= 0
:dataclass[A decorator that auto-generates __init__, __repr__, and __eq__ from class attributes with type annotations]es — auto-generate __init__, __repr__, __eq__: ``python from dataclasses import dataclass, field @dataclass class Point: x: float y: float label: str = "origin" tags: list = field(default_factory=list) p = Point(1.0, 2.0) # __init__, __repr__, __eq__ all generated automatically
:MRO[Method Resolution Order — the order Python searches for methods in multiple inheritance] (Method Resolution Order) — how Python resolves method calls in multiple inheritance: ``python class A: def greet(self): return "A" class B(A): def greet(self): return "B" class C(A): def greet(self): return "C" class D(B, C): pass # MRO: D → B → C → A D().greet() # "B" — follows MRO left to right print(D.__mro__) # (<class D>, <class B>, <class C>, <class A>, <class object>)
Examples
dataclass with validation
__post_init__ runs after the generated __init__ — great for validation
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
email: str
def __post_init__(self):
if self.age < 0:
raise ValueError("Age cannot be negative")
self.email = self.email.lower()
u = User("Alice", 30, "Alice@Example.COM")
print(u) # User(name='Alice', age=30, email='alice@example.com')classmethod as alternative constructor
classmethods let you define multiple ways to construct an object
from dataclasses import dataclass
from datetime import date
@dataclass
class Event:
name: str
date: date
@classmethod
def today(cls, name: str) -> "Event":
return cls(name, date.today())
@classmethod
def from_iso(cls, name: str, iso: str) -> "Event":
return cls(name, date.fromisoformat(iso))
e = Event.from_iso("Launch", "2026-07-01")How well did you understand this?
Next in Python Core
Context Managers