Aufgaben-Python/02_init_und_self/README.md

89 lines
3 KiB
Markdown

# Kapitel 02: Der Konstruktor `__init__` und das geheimnisvolle `self` 💳
Im ersten Kapitel haben wir Attribute noch manuell nach dem Erstellen zugewiesen:
```python
bello = Haustier()
bello.name = "Bello"
bello.alter = 3
```
Das ist mühsam und fehleranfällig: Was passiert, wenn man vergisst, `.alter` zu setzen? Richtig: Das Programm stürzt ab, sobald jemand darauf zugreift!
Deshalb gibt es in Python den **Konstruktor**: `__init__`.
---
## 🛠️ Was ist `__init__`?
`__init__` steht für *initialisieren* (vorbereiten/startklar machen).
Es ist eine **spezielle Methode**, die Python **automatisch aufruft**, sobald du ein neues Objekt erstellst.
---
## 📱 Vollständiges Praxisbeispiel: Die Smartphone-Klasse
```python
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%
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!"
def aufladen(self):
self.akku = 100
return f"{self.modell} ist wieder voll aufgeladen (100%)!"
# Verwendung:
mein_handy = Smartphone("iPhone 15", 256)
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%
```
---
## 🪞 Was bedeutet eigentlich `self`?
- `self` bedeutet auf Deutsch **"ich selbst"** oder **"dieses konkrete Objekt hier"**.
- Wenn du `mein_handy.benutzen(30)` aufrufst, übergibt Python das neu entstandene `mein_handy`-Objekt automatisch als erstes Argument `self`.
- `self.akku -= verbrauch` zieht den Strom genau vom Akku dieses einen Handys ab.
---
## ⚠️ Typische Fehler vermeiden
1. **`__init__` mit zwei Unterstrichen schreiben:**
- ❌ `def _init_(self):` (wird nicht aufgerufen!)
- ✅ `def __init__(self):` (korrekt!)
2. **`self` bei jeder Methode als ersten Parameter:**
- ❌ `def einzahlen(betrag):` -> führt zu `TypeError: einzahlen() takes 1 positional argument but 2 were given`
- ✅ `def einzahlen(self, betrag):`
3. **Zuweisungsrichtung beachten:**
- ❌ `inhaber = self.inhaber` (falsch herum!)
- ✅ `self.inhaber = inhaber` (speichert den Parameter im Attribut)
---
## 🎯 Deine Aufgabe: Das Bankkonto
Öffne `aufgabe.py`. Du programmierst eine Klasse `Bankkonto`:
1. Schreibe den Konstruktor `__init__`.
2. Ergänze Methoden zum Einzahlen (`einzahlen`) und Auszahlen (`auszahlen`), die darauf achten, dass man nicht ins Minus rutscht.
3. Ergänze eine Methode `info_text()`.
### Testen:
```bash
python3 test_aufgabe.py
```