Ab hier wird Python richtig mächtig – mit

OOP

( Objektorientiertes Programmieren )

# class · object · __init__ · self · inheritance · polymorphism

# Mini-Vorschau: Klasse + Objekt
class User:
def __init__(self, name):
self.name = name
def say_hi(self):
print(f"Hi, ich bin {{"{self.name}"}}!")

u1 = User("Bastian")
u1.say_hi() # → Hi, ich bin Bastian!

Was bedeutet Objektorientierung?

OOP (Objektorientierte Programmierung) bedeutet: Du modellierst deinen Code wie die echte Welt. Statt nur Funktionen und Variablen zu verteilen, packst du Daten (Attribute) und Funktionen (Methoden) in eine gemeinsame Einheit: ein Objekt.

🧩
Klasse
Bauplan / Vorlage. Definiert, welche Eigenschaften und Methoden Objekte haben.
📦
Objekt
Ein konkretes „Ding“, das aus der Klasse erstellt wurde (Instanz).
🔁
Wiederverwendbarkeit
Du kannst Strukturen sauber wiederverwenden und erweitern (z.B. Vererbung).
💡
OOP ist kein „Muss“. Für kleine Skripte reicht oft prozeduraler Code. Aber sobald ein Projekt wächst, wird OOP übersichtlicher und wartbarer.

class & Instanzen

Eine Klasse definierst du mit class. Ein Objekt entsteht, wenn du die Klasse „aufrufst“ wie eine Funktion.

klassen.py
# Klasse (Bauplan) class Hund: pass # (später füllen) # Objekt / Instanz h1 = Hund() h2 = Hund() print(h1, h2) # zwei verschiedene Objekte
Klassenname
Klassen schreibt man in Python meistens in PascalCase (z.B. MeineKlasse).
class UserAccount: ... ✓
Instanz
Ein Objekt ist eine Instanz einer Klasse – also ein „konkreter Bauplan-Abdruck“.
user1 = User() ✓

__init__ (Konstruktor)

Wenn du ein Objekt erzeugst, kann Python automatisch eine Start-Logik ausführen: __init__. Hier setzt du häufig Startwerte (Attribute).

init.py
class User: def __init__(self, name, rolle="User"): self.name = name self.rolle = rolle u1 = User("Bastian") u2 = User("Sarah", "Admin") print(u1.name, u1.rolle) # Bastian User print(u2.name, u2.rolle) # Sarah Admin
⚠️
Merke: self ist Pflicht als erster Parameter in Methoden. Er zeigt auf das aktuelle Objekt, damit du auf Attribute wie self.name zugreifen kannst.

Instanzattribute vs. Klassenattribute

Instanzattribute gehören zu einem bestimmten Objekt. Klassenattribute gehören zur Klasse selbst und werden von allen Instanzen geteilt.

📌
Instanzattribute
Werden meistens in __init__ über self gesetzt.
class User:
def __init__(self, name):
self.name = name
🏷️
Klassenattribute
Stehen direkt in der Klasse – ohne self.
class User:
plattform = "HelloPython.de"
def __init__(self, name):
self.name = name
💡
Klassenattribute eignen sich z.B. für Konstanten (Version, Name, Limits) oder Zähler. Alles, was pro Objekt unterschiedlich ist, gehört meistens in Instanzattribute.

Methoden & self

Methoden sind Funktionen innerhalb einer Klasse. Der wichtigste Punkt: Der erste Parameter ist fast immer self.

methoden.py
class Konto: def __init__(self, inhaber, saldo=0): self.inhaber = inhaber self.saldo = saldo def einzahlen(self, betrag): self.saldo += betrag def anzeigen(self): print(f"Konto {{"{self.inhaber}"}}: {{"{self.saldo}"}} €") k = Konto("Bastian", 50) k.einzahlen(25) k.anzeigen() # Konto Bastian: 75 €
Warum self?
Weil Python wissen muss, auf welches Objekt du dich beziehst. So werden Methoden „objektbezogen“.
self.saldo += betrag ✓
Methoden vs. Funktionen
Eine Funktion steht „frei“. Eine Methode ist eine Funktion in einer Klasse und arbeitet meistens mit self.
print(x) Funktion · obj.methode() Methode

Kapselung & Properties

Kapselung bedeutet: Du schützt interne Daten, damit sie nicht „wild“ verändert werden. In Python gibt es kein echtes private wie in Java – aber es gibt Konventionen: _name (intern) und __name (Name Mangling). Für kontrollierten Zugriff nutzt man oft @property.

property.py
class Temperatur: def __init__(self, celsius): self._c = celsius # '_' = interne Variable @property def celsius(self): return self._c @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("Unter absolutem Nullpunkt!") self._c = value t = Temperatur(20) print(t.celsius) # Getter t.celsius = 30 # Setter (mit Prüfung)
🔒
Warum Properties? Du kannst Werte validieren (prüfen), bevor du sie setzt. So bleibt dein Objekt „gesund“ und dein Code wird robuster.

Vererbung (Inheritance)

Vererbung bedeutet: Eine Klasse kann Eigenschaften/Methoden von einer anderen Klasse übernehmen. Die „Kindklasse“ erweitert oder überschreibt das Verhalten der „Elternklasse“.

vererbung.py
class Tier: def __init__(self, name): self.name = name def sound(self): return "..." class Hund(Tier): def sound(self): return "Wuff" class Katze(Tier): def sound(self): return "Miau" tiere = [Hund("Rex"), Katze("Luna")] for t in tiere: print(t.name, t.sound())
🧬
Wenn du Konstruktor-Logik aus der Elternklasse brauchst, nutzt du oft super().__init__(...) in der Kindklasse.

Gleiches Interface, unterschiedliches Verhalten

Polymorphismus bedeutet: Verschiedene Objekte können dieselbe Methode besitzen, aber unterschiedlich reagieren. Im Beispiel oben haben Hund und Katze beide sound() – aber mit unterschiedlichem Ergebnis.

🎭
Warum praktisch?
Du kannst über eine Liste von Objekten iterieren, ohne zu wissen, welche konkrete Klasse jedes Objekt hat.
Merksatz
„Wenn es wie eine Ente quakt …“ – Duck Typing: Entscheidend ist, welche Methoden ein Objekt hat.

Komposition statt Vererbung

Komposition bedeutet: Ein Objekt besteht aus anderen Objekten. Oft ist das flexibler als Vererbung ("has-a" statt "is-a").

komposition.py
class Motor: def start(self): return "Motor läuft" class Auto: def __init__(self): self.motor = Motor() # Auto "hat" einen Motor def starten(self): return self.motor.start() a = Auto() print(a.starten())
🧱
Faustregel: Nutze Vererbung, wenn wirklich eine „ist-ein“-Beziehung existiert. Ansonsten ist Komposition oft sauberer.

@classmethod & @staticmethod

Neben normalen Methoden gibt es: @classmethod (arbeitet mit der Klasse selbst) und @staticmethod (wie eine Funktion, aber logisch in der Klasse gruppiert).

🏷️
@classmethod
Erster Parameter ist cls (die Klasse). Praktisch für alternative Konstruktoren.
class User:
def __init__(self, name):
self.name = name
@classmethod
def guest(cls):
return cls("Gast")
🧰
@staticmethod
Kein self und kein cls. Gut für kleine Hilfsfunktionen.
class Math:
@staticmethod
def is_even(n):
return n % 2 == 0

Dunder-Methoden ("__...__")

Dunder-Methoden (double underscore) geben deinen Objekten „Superkräfte“. Damit funktionieren Dinge wie print(obj) oder len(obj).

Methode Wann wird sie genutzt? Beispiel
__str__ Bei print(obj) / str(obj) return "User: ..."
__repr__ Debug-Ansicht (z.B. in Listen) return "User(name=...)"
__len__ Bei len(obj) return len(self.items)
__add__ Bei a + b return ...
__eq__ Bei a == b return self.id == other.id
dunder.py
class Playlist: def __init__(self, name): self.name = name self.songs = [] def add(self, title): self.songs.append(title) def __len__(self): return len(self.songs) def __str__(self): return f"Playlist '{{"{self.name}"}}' ({{"{len(self)}"}} Songs)" p = Playlist("Coding") p.add("Song 1") print(len(p)) # 1 print(p) # Playlist 'Coding' (1 Songs)

Mini-Projekt: Aufgabenliste als Klasse

Ein kleines Projekt, das du direkt in VS Code ausprobieren kannst: Eine ToDo-Liste mit Tasks. Dabei übst du: Klassen, Listen, Methoden, Dunder und saubere Struktur.

todo_oop.py
class Task: def __init__(self, title): self.title = title self.done = False def toggle(self): self.done = not self.done def __str__(self): mark = "✅" if self.done else "⬜" return f"{{"{mark}"}} {{"{self.title}"}}" class TodoList: def __init__(self): self.tasks = [] def add(self, title): self.tasks.append(Task(title)) def toggle(self, index): self.tasks[index].toggle() def __len__(self): return len(self.tasks) def show(self): for i, t in enumerate(self.tasks): print(f"{{"{i}"}}. {{"{t}"}}") todo = TodoList() todo.add("OOP-Seite fertigstellen") todo.add("Tests schreiben") todo.show() todo.toggle(0) todo.show()
🚀
Challenge: Baue remove(index) und clear_done() dazu. Bonus: Schreibe eine Methode save_to_file() und speichere die Tasks in eine Textdatei.
Weiter lernen

Nice! Du hast die wichtigsten OOP-Bausteine verstanden. Als nächstes passen perfekt: Fehlerbehandlung (try/except) und Module & Pakete.