it-praxisportal/13_persistenz_json_und_csv/musterloesung.py

143 lines
5.3 KiB
Python

"""
Kapitel 13: Datei-Persistenz (JSON & CSV) 💾📁
==============================================
Musterlösung für JSON- und CSV-Persistenz in Python OOP.
"""
import json
import csv
from pathlib import Path
from typing import List, Optional, Dict, Any
# ==============================================================================
# 1. Klasse Spieler mit to_dict / from_dict
# ==============================================================================
class Spieler:
def __init__(self, name: str, level: int, punkte: int, inventar: Optional[List[str]] = None):
"""Initialisiert ein Spieler-Objekt."""
self.name: str = name
self.level: int = int(level)
self.punkte: int = int(punkte)
self.inventar: List[str] = list(inventar) if inventar is not None else []
def to_dict(self) -> Dict[str, Any]:
"""Konvertiert das Objekt in ein speicherbares Dictionary."""
return {
"name": self.name,
"level": self.level,
"punkte": self.punkte,
"inventar": self.inventar,
}
@classmethod
def from_dict(cls, daten: Dict[str, Any]) -> "Spieler":
"""Erstellt ein neues Spieler-Objekt aus einem Dictionary."""
return cls(
name=daten["name"],
level=int(daten["level"]),
punkte=int(daten["punkte"]),
inventar=list(daten.get("inventar", [])),
)
def __repr__(self) -> str:
return f"Spieler(name='{self.name}', level={self.level}, punkte={self.punkte}, inventar={self.inventar})"
def __eq__(self, other: object) -> bool:
if not isinstance(other, Spieler):
return False
return (
self.name == other.name
and self.level == other.level
and self.punkte == other.punkte
and self.inventar == other.inventar
)
# ==============================================================================
# 2. Klasse Spielstand mit JSON & CSV Persistenz
# ==============================================================================
class Spielstand:
def __init__(self, titel: str = "Neuer Spielstand"):
"""Initialisiert einen Spielstand mit Titel und leerer Spielerliste."""
self.titel: str = titel
self.spieler_liste: List[Spieler] = []
def spieler_hinzufuegen(self, spieler: Spieler) -> None:
"""Fügt einen Spieler hinzu."""
self.spieler_liste.append(spieler)
def spieler_suchen(self, name: str) -> Optional[Spieler]:
"""Findet einen Spieler anhand seines Namens."""
for s in self.spieler_liste:
if s.name == name:
return s
return None
def bester_spieler(self) -> Optional[Spieler]:
"""Gibt den Spieler mit der höchsten Punktzahl zurück."""
if not self.spieler_liste:
return None
return max(self.spieler_liste, key=lambda s: s.punkte)
def speichern_als_json(self, dateipfad: str | Path) -> None:
"""Speichert den gesamten Zustand als JSON auf der Festplatte."""
pfad = Path(dateipfad)
daten = {
"titel": self.titel,
"spieler": [s.to_dict() for s in self.spieler_liste],
}
with open(pfad, "w", encoding="utf-8") as f:
json.dump(daten, f, indent=4, ensure_ascii=False)
def laden_aus_json(self, dateipfad: str | Path) -> None:
"""Lädt den Spielstand aus einer JSON-Datei."""
pfad = Path(dateipfad)
with open(pfad, "r", encoding="utf-8") as f:
daten = json.load(f)
self.titel = daten.get("titel", self.titel)
spieler_rohdaten = daten.get("spieler", [])
self.spieler_liste = [Spieler.from_dict(d) for d in spieler_rohdaten]
def exportiere_als_csv(self, dateipfad: str | Path) -> None:
"""Exportiert eine tabellarische Zusammenfassung als CSV-Datei."""
pfad = Path(dateipfad)
feldnamen = ["name", "level", "punkte", "inventar_anzahl"]
with open(pfad, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=feldnamen)
writer.writeheader()
for s in self.spieler_liste:
writer.writerow({
"name": s.name,
"level": s.level,
"punkte": s.punkte,
"inventar_anzahl": len(s.inventar),
})
def importiere_aus_csv(self, dateipfad: str | Path) -> int:
"""Importiert Spieler aus einer CSV-Datei."""
pfad = Path(dateipfad)
importierte_anzahl = 0
with open(pfad, "r", newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for zeile in reader:
neuer_spieler = Spieler(
name=zeile["name"],
level=int(zeile["level"]),
punkte=int(zeile["punkte"]),
inventar=[]
)
self.spieler_hinzufuegen(neuer_spieler)
importierte_anzahl += 1
return importierte_anzahl
if __name__ == "__main__":
spielstand = Spielstand("Musterloesung Spielstand")
spielstand.spieler_hinzufuegen(Spieler("Gandalf", 99, 99999, ["Stab", "Ring"]))
spielstand.speichern_als_json("test_muster.json")
print("Erfolgreich ausgeführt!")