Aufwärmen · Aufgabe 1 von 7
Aufwärmen aus Modul B4: Methoden auf Objekten rufen Sie seit den ersten Modulen auf. Was gibt das aus?
names = ["bob", "ada"]
names.sort()
print(names, "hi".upper())// I2.2 · ca. 30 Min. · Aufbau
Nach dieser Lektion definieren Sie eine Klasse mit __init__ und Methoden, erzeugen Instanzen mit jeweils eigenen Daten und wählen zwischen Instanz- und Klassenvariablen.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
names = ["bob", "ada"]
names.sort()
print(names, "hi".upper())Vorhersagen · Aufgabe 2 von 7
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
a = Counter()
b = Counter()
a.increment()
a.increment()
b.increment()
print(a.count, b.count)Üben · Aufgabe 3 von 7
class Point:
def __init__(self, x, y):
____.x = x
self.y = yÜben · Aufgabe 4 von 7
class Dog:
kind = "canine"
def __init__(self, name):
self.name = name
d = Dog("Fido")
e = Dog("Buddy")
e.kind = "robot"
print(d.kind, e.kind, Dog.kind)Üben · Aufgabe 5 von 7
Denksport · Aufgabe 6 von 7
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
d = Dog("Fido")
e = Dog("Buddy")
d.add_trick("roll over")
e.add_trick("play dead")
print(d.tricks)Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Jeder Cart speichert seinen Besitzer und eine eigene Liste von Positionen, angelegt in __init__. Die Methoden rufen einander über self auf: summary nutzt total, total nutzt net. vat_rate ist eine Klassenvariable; eine Änderung an der Klasse gilt also für jeden Warenkorb. Die dritte Zeile zeigt, dass ein Methodenaufruf die Funktion der Klasse ist, mit der Instanz als self.
main.py
class Cart:
"""A shopping cart that holds (name, price, quantity) lines."""
vat_rate = 0.19 # class variable: the same for every cart
def __init__(self, owner: str) -> None:
self.owner = owner
self.lines: list[tuple[str, float, int]] = [] # a new list for each cart
def add(self, name: str, price: float, quantity: int = 1) -> None:
self.lines.append((name, price, quantity))
def net(self) -> float:
return sum(price * quantity for _, price, quantity in self.lines)
def total(self) -> float:
return round(self.net() * (1 + self.vat_rate), 2)
def summary(self) -> str:
count = sum(quantity for _, _, quantity in self.lines)
return f"{self.owner}: {count} item(s), {self.total():.2f} EUR"
ada = Cart("ada")
ada.add("coffee", 8.50, 2)
ada.add("mug", 12.00)
bob = Cart("bob")
bob.add("tea", 4.20)
print(ada.summary())
print(bob.summary())
print(Cart.summary(bob) == bob.summary())
Cart.vat_rate = 0.07 # changes it for every cart
print(ada.summary())
Ausführen mit
python main.pyAusgabe
ada: 3 item(s), 34.51 EUR
bob: 1 item(s), 5.00 EUR
True
ada: 3 item(s), 31.03 EURTab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
Übung 1 von 2
Vervollständigen Sie die Klasse Book. Book(title, pages) speichert beides und beginnt mit current_page bei 0. read(n) rückt current_page um n Seiten vor, aber nie über die letzte Seite hinaus, und liefert das neue current_page. is_finished() liefert True, sobald current_page gleich pages ist. Jedes Buch merkt sich seinen eigenen Fortschritt.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
Setzen Sie self.current_page = 0 in __init__, neben title und pages.
Addieren Sie in read n zu self.current_page und begrenzen Sie mit min(..., self.pages), damit es nicht über die letzte Seite geht.
is_finished liefert den Vergleich selbst: return self.current_page == self.pages.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
class Book:
def __init__(self, title: str, pages: int) -> None:
self.title = title
self.pages = pages
self.current_page = 0
def read(self, n: int) -> int:
"""Read n pages, stopping at the last page; return the current page."""
self.current_page = min(self.current_page + n, self.pages)
return self.current_page
def is_finished(self) -> bool:
return self.current_page == self.pages
Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.py
class Book:
def __init__(self, title: str, pages: int) -> None:
self.title = title
self.pages = pages
def read(self, n: int) -> int:
"""Read n pages, stopping at the last page; return the current page."""
return 0
def is_finished(self) -> bool:
return False
test_main.py
from main import Book
def test_starts_at_zero():
"""Ein neues Buch beginnt bei Seite 0"""
book = Book("Dune", 600)
got = getattr(book, "current_page", None)
assert got == 0, f"current_page eines neuen Buchs ist {got!r}, erwartet: 0"
def test_read_moves_on():
"""read(n) addiert n Seiten und liefert die neue Seite"""
book = Book("Dune", 600)
got = book.read(40), book.read(10)
assert got == (40, 50), f"read(40), read(10) lieferten {got!r}, erwartet: (40, 50)"
def test_stops_at_last_page():
"""read geht nie über die letzte Seite hinaus"""
book = Book("Emma", 100)
got = book.read(250)
assert got == 100, f"read(250) bei einem Buch mit 100 Seiten lieferte {got!r}, erwartet: 100"
def test_finished():
"""is_finished ist erst auf der letzten Seite True"""
book = Book("Emma", 100)
book.read(99)
assert book.is_finished() is False, "is_finished() ist auf Seite 99 von 100 schon True"
book.read(1)
assert book.is_finished() is True, "is_finished() ist auf Seite 100 von 100 noch False"
def test_separate_books():
"""Zwei Bücher merken sich ihren Fortschritt getrennt"""
a = Book("A", 50)
b = Book("B", 50)
a.read(20)
assert b.read(5) == 5, "das Lesen in Buch a hat den Fortschritt von Buch b verändert"
Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.
Programm ausführen:
python main.pyPrüfungen ausführen (learnrun.py muss im selben Ordner liegen):
python learnrun.py testlearnrun.py herunterladenÜbung 2 von 2
Jedes Ticket soll die nächste Nummer bekommen: 1, 2, 3 und so weiter, gezählt in der Klassenvariable issued. Jedes Ticket hat außerdem eine eigene Liste von Sitzplätzen. Der Starter hat zwei Fehler: Jedes Ticket bekommt die Nummer 1, und alle Tickets teilen sich eine seats-Liste. Beheben Sie beide und lassen Sie issued auf der Klasse.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.
self.issued += 1 liest die Klassenvariable, legt dann aber ein Instanzattribut an. Ändern Sie die Klassenvariable über die Klasse: Ticket.issued += 1.
Eine Liste im Klassenrumpf teilen sich alle Tickets. Legen Sie self.seats = [] stattdessen in __init__ an.
Entfernen Sie die seats-Zeile aus dem Klassenrumpf und ergänzen Sie self.seats: list[str] = [] in __init__.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
class Ticket:
issued = 0
def __init__(self, event: str) -> None:
self.event = event
Ticket.issued += 1
self.number = Ticket.issued
self.seats: list[str] = []
def add_seat(self, seat: str) -> None:
self.seats.append(seat)
Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.py
class Ticket:
issued = 0
seats: list[str] = []
def __init__(self, event: str) -> None:
self.event = event
self.issued += 1
self.number = self.issued
def add_seat(self, seat: str) -> None:
self.seats.append(seat)
test_main.py
from main import Ticket
def test_numbers_count_up():
"""Tickets bekommen die Nummern 1, 2, 3"""
Ticket.issued = 0
got = [Ticket("concert").number for _ in range(3)]
assert got == [1, 2, 3], f"drei Tickets bekamen die Nummern {got!r}, erwartet: [1, 2, 3]"
def test_class_counter():
"""issued auf der Klasse zählt jedes Ticket"""
Ticket.issued = 0
Ticket("play")
Ticket("play")
assert Ticket.issued == 2, f"Ticket.issued ist nach zwei Tickets {Ticket.issued!r}, erwartet: 2"
def test_own_seats():
"""Jedes Ticket hat eine eigene Liste von Sitzplätzen"""
a = Ticket("film")
b = Ticket("film")
a.add_seat("A1")
b.add_seat("B7")
assert a.seats == ["A1"], f"a.seats ist {a.seats!r}, erwartet: ['A1']"
assert b.seats == ["B7"], f"b.seats ist {b.seats!r}, erwartet: ['B7']"
Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.
Programm ausführen:
python main.pyPrüfungen ausführen (learnrun.py muss im selben Ordner liegen):
python learnrun.py testlearnrun.py herunterladenclass Greeter:
def hello():
return "hello"
Greeter().hello()
Was Python ausgibt
TypeError: Greeter.hello() takes 0 positional arguments but 1 was givenWarum, und die Lösung
Ein Methodenaufruf übergibt immer die Instanz als erstes Argument, also braucht jede Methode einen Parameter, der sie aufnimmt. Schreiben Sie def hello(self):. Die Fehlermeldung zählt dieses versteckte Argument mit: Das „1 was given“ ist die Instanz selbst.
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14159 * radius ** 2
print(Circle(2).area())
Was Python ausgibt
NameError: name 'radius' is not definedWarum, und die Lösung
radius war ein Parameter von __init__ und verschwand, als __init__ zurückkehrte. Übrig bleibt das Attribut self.radius. Greifen Sie in einer Methode immer über self auf die Daten des Objekts zu: 3.14159 * self.radius ** 2.
class Circle:
def __init__(self, radius):
self.radius = radius
c = Circle()
Was Python ausgibt
TypeError: Circle.__init__() missing 1 required positional argument: 'radius'Warum, und die Lösung
Die Argumente von Circle(...) gehen an __init__, nach self. __init__ braucht einen radius, also übergeben Sie einen: Circle(2). Gibt es einen sinnvollen Standardwert, geben Sie dem Parameter stattdessen einen: def __init__(self, radius=1.0):.
Python im Browser: Pyodide 314.0.7, MPL-2.0. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.