Kapitel 02

Der Konstruktor __init__ & das geheimnisvolle self 💳

Lerne, wie Objekte direkt beim Erstellen startklar gemacht werden – mit vollständigen Codebeispielen.

📂 Dateien dieser Einheit:
💻 In Web-IDE öffnen → 📄 aufgabe.py (Startercode) 🧪 test_aufgabe.py (Tests) 💡 musterloesung.py (Lösung) 📖 README.md

1. Warum brauchen wir __init__?

In Kapitel 01 mussten wir jedes Attribut mühsam nach dem Erstellen von Hand setzen:

bello = Haustier()
bello.name = "Bello"
bello.alter = 3  # Wenn wir 100 Tiere haben, müssen wir hunderte Zeilen schreiben!

Die Lösung heißt Konstruktor: Die spezielle Methode __init__. Sie wird von Python automatisch aufgerufen, genau in dem Moment, in dem du ein Objekt erzeugst!

2. 📱 Vollständiges Beispiel: Die Smartphone-Klasse

Schau dir an, wie eine vollständige Klasse mit Konstruktor und Methoden in der Praxis aussieht:

Python (Komplettes Beispiel: smartphone.py)
# 1. Die vollständige Klasse definieren:
class Smartphone:
    # Der Konstruktor wird automatisch beim Erstellen aufgerufen:
    def __init__(self, modell, speicher_gb, akku=100):
        self.modell = modell              # z.B. "iPhone 15"
        self.speicher_gb = speicher_gb      # z.B. 128
        self.akku = akku                  # Standardwert ist 100%

    # Eine Methode, die den Akkustand verringert:
    def benutzen(self, minuten):
        verbrauch = minuten * 0.5
        if self.akku >= verbrauch:
            self.akku -= verbrauch
            return f"{self.modell}: {minuten} Min. genutzt. Akku: {self.akku:.0f}%"
        else:
            self.akku = 0
            return f"{self.modell}: Akku ist leer!"

    # Eine Methode zum Aufladen:
    def aufladen(self):
        self.akku = 100
        return f"{self.modell} ist wieder voll aufgeladen (100%)!"


# ==============================================================================
# Jetzt verwenden wir die Smartphone-Klasse:
# ==============================================================================
if __name__ == "__main__":
    # Handy 1 erstellen (nutzt Standard-Akku 100%):
    mein_handy = Smartphone("iPhone 15", 256)

    # Handy 2 erstellen (mit 40% Start-Akku):
    altes_handy = Smartphone("Galaxy S10", 64, akku=40)

    print(mein_handy.benutzen(30))   # Verbraucht 15% -> 85% Rest
    print(altes_handy.benutzen(90))  # Akku wird leer!
    print(altes_handy.aufladen())     # Wieder 100%

3. Was bedeutet self ganz genau?

Das Wörtchen self steht für "dieses konkrete Objekt hier".

🪞 Das Namensschild-Prinzip:
Wenn du mein_handy.benutzen(30) aufrufst, übergibt Python im Hintergrund automatisch mein_handy als erstes Argument self.

self.akku -= verbrauch bedeutet: "Ziehe den Verbrauch vom Akku DIESES Handys ab – nicht von allen anderen Handys auf der Welt!"
💡 Warum self.inhaber = inhaber?
  • Links (self.inhaber): Das Attribut, das fest am Objekt im Arbeitsspeicher abgespeichert wird.
  • Rechts (inhaber): Der Wert, den jemand beim Aufruf in die Klammern übergeben hat.

4. ⚠️ Häufige Fehler beim Konstruktor

1. Tippfehler bei den Unterstrichen:
def __init__(self):  ✓ (2 Unterstriche vorne, 2 hinten: Dunder!)
def _init_(self):  ✗ (Falsch! Python ruft die Methode nicht auf!)
2. 'self' im Methodenkopf vergessen:
def einzahlen(self, betrag):  ✓
def einzahlen(betrag):  ✗ (Führt zu TypeError: takes 1 positional argument but 2 were given)
3. Falsche Zuweisungsrichtung:
self.kontostand = kontostand  ✓
kontostand = self.kontostand  ✗ (Überschreibt den Parameter, speichert nichts am Objekt!)

5. 🎯 Deine Aufgaben in aufgabe.py

Öffne die Datei aufgabe.py:

💡 Lösungshinweise (Aufklappen bei Bedarf)

🔍 Tipp zu TODO 3 (Auszahlen mit Absicherung)
def auszahlen(self, betrag):
    if betrag > 0 and self.kontostand >= betrag:
        self.kontostand -= betrag
        return True
    return False

6. 🧪 Lösung überprüfen

Führe im Terminal im Ordner 02_init_und_self folgenden Befehl aus:

Terminal
python3 test_aufgabe.py