Objektorienteret Python
Classes, dataclasses, composition, inheritance og tydelige interfaces.
Objekter er nyttige, når data og adfærd hører naturligt sammen. Brug ikke en class, hvis en simpel funktion og dictionary er tydeligere.
En lille class
class BankAccount:
def __init__(self, owner: str, balance: int = 0) -> None:
self.owner = owner
self._balance = balance
def deposit(self, amount: int) -> None:
if amount <= 0:
raise ValueError("Beløbet skal være positivt")
self._balance += amount
@property
def balance(self) -> int:
return self._balanceDataclasses til data
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class User:
id: int
name: str
roles: tuple[str, ...] = field(default_factory=tuple)frozen=True gør objektet uforanderligt. slots=True reducerer hukommelsesforbrug og forhindrer tilfældige nye attributes.
Composition før inheritance
class EmailSender:
def send(self, address: str, message: str) -> None:
print(f"Sender til {address}: {message}")
class RegistrationService:
def __init__(self, sender: EmailSender) -> None:
self.sender = sender
def register(self, address: str) -> None:
self.sender.send(address, "Velkommen")RegistrationService bruger en sender i stedet for at arve fra den. Det gør delene lettere at udskifte og teste.
Hvornår inheritance giver mening
Inheritance passer bedst til et ægte “er en”-forhold med en stabil baseklasse. Brug Protocol til fleksible interfaces, når flere forskellige classes blot skal tilbyde samme metoder.
Øvelse
Byg et lagersystem med Product, Inventory og en udskiftelig Storage-implementation. Lav først memory storage og derefter JSON storage uden at ændre Inventory.