Avanceret
Iterators, generators, decorators, context managers, async og moderne Python-design.
Iterators og generators
En iterable kan levere en iterator. En iterator returnerer værdier én ad gangen og stopper med StopIteration.
def read_chunks(path, size: int = 8192):
with open(path, "rb") as file:
while chunk := file.read(size):
yield chunkGenerators bruger yield og behøver ikke holde alle værdier i hukommelsen samtidig.
Decorators
from functools import wraps
from time import perf_counter
def timed(function):
@wraps(function)
def wrapper(*args, **kwargs):
start = perf_counter()
try:
return function(*args, **kwargs)
finally:
print(f"{function.__name__}: {perf_counter() - start:.4f}s")
return wrapper
@timed
def calculate():
return sum(range(1_000_000))Decorators er gode til tværgående adfærd som logging, caching og adgangskontrol. De må ikke skjule vigtige sideeffekter.
Context managers
from contextlib import contextmanager
@contextmanager
def transaction(connection):
try:
yield connection
connection.commit()
except Exception:
connection.rollback()
raiseContext managers gør setup og cleanup eksplicit med with.
Async IO
import asyncio
async def worker(name: str, delay: float) -> str:
await asyncio.sleep(delay)
return f"{name} færdig"
async def main() -> None:
results = await asyncio.gather(
worker("A", 1.0),
worker("B", 0.5),
)
print(results)
asyncio.run(main())Async passer til mange samtidige ventende operationer som netværk og databaser. Det gør ikke CPU-tung kode hurtigere.
Protocols og dependency injection
from typing import Protocol
class UserStore(Protocol):
def get_name(self, user_id: int) -> str | None: ...
def greet(user_id: int, store: UserStore) -> str:
return store.get_name(user_id) or "Ukendt"Protocol beskriver den adfærd, en dependency skal have, uden at kræve nedarvning.
Packaging
Et moderne bibliotek bruger normalt pyproject.toml, en importérbar package, tests og et tydeligt CLI-entrypoint. Hold runtime-dependencies adskilt fra development-dependencies.
Hvornår er koden avanceret på den gode måde?
- Abstraktionen fjerner reel gentagelse eller kobling.
- Fejl og ressource-cleanup er tydelige.
- Koden kan testes uden netværk eller globale objekter.
- En simplere løsning er blevet vurderet først.