Keksdose
Quelle: Sesame Street
Aufgabe
So funktioniert die Keksdose
- Kapazität: Beim Anlegen legt
capacityfest, wie viele Kekse höchstens hineinpassen; ohne Angabe sind es 12. Istcapacitykeine positive Ganzzahl (int), etwa0,-5oder"ten", gibt es einenValueError. - Anfangs leer: Eine neue Dose enthält 0 Kekse.
- Hineinlegen:
deposit(n)legtnKekse hinein. Würde die Dose dadurch mehr Kekse enthalten, alscapacityerlaubt, gibt es einenValueError. - Herausnehmen:
withdraw(n)nimmtnKekse heraus. Sind weniger alsnKekse in der Dose, gibt es einenValueError. - Negative Anzahl: Ist
nbeidepositoderwithdrawnegativ, gibt es ebenfalls einenValueError. - Fehler ändern nichts: Nach einem
ValueErrorenthält die Dose so viele Kekse wie vorher. - Anzeige:
str(jar)liefert für jeden Keks in der Dose ein🍪, bei einer leeren Dose also"". - Abfragen:
jar.capacityliefert die Kapazität,jar.sizedie Zahl der Kekse in der Dose. Beide sind Properties: Man schreibt sie ohne Klammern und kann sie von außen nur lesen.
Beispiel mit einer Dose für 10 Kekse:
| Aufruf | Ergebnis | jar.size | str(jar) |
|---|---|---|---|
jar = Jar(10) | neue, leere Dose | 0 | "" |
jar.deposit(8) | 8 | 🍪🍪🍪🍪🍪🍪🍪🍪 | |
jar.withdraw(3) | 5 | 🍪🍪🍪🍪🍪 | |
jar.deposit(6) | ValueError: 5 + 6 = 11 ist mehr als 10 | 5 | 🍪🍪🍪🍪🍪 |
jar.withdraw(6) | ValueError: nur 5 Kekse in der Dose | 5 | 🍪🍪🍪🍪🍪 |
jar.deposit(5) | Dose ist voll | 10 | 🍪🍪🍪🍪🍪🍪🍪🍪🍪🍪 |
Jar(0) | ValueError: Kapazität muss positiv sein |
Demo
Ein Hauptprogramm brauchen Sie nicht (Sie dürfen aber eines schreiben). Mehr als das hier gibt es also nicht vorzuführen:
Quelle: Sesame Street
Spezifikation
Implementieren Sie in
jar.pyim Ordnerjareine KlasseJarmit genau diesem Aufbau. Die Parameter der Methoden dürfen Sie nicht ändern; eigene Methoden dürfen Sie ergänzen.class Jar: def __init__(self, capacity=12): ... def __str__(self): ... def deposit(self, n): ... def withdraw(self, n): ... @property def capacity(self): ... @property def size(self): ...__init__prüft die Kapazität nach Regel 1 und legt eine leere Dose an (Regel 2).depositundwithdrawändern die Zahl der Kekse nach den Regeln 3 bis 6.__str__gibt die Kekse als String zurück (Regel 7).capacityundsizegeben die Kapazität bzw. die aktuelle Zahl der Kekse zurück (Regel 8).Schreiben Sie in
test_jar.pymindestens vier Funktionen, deren Name mittest_beginnt und die Ihre Klasse zusammen gründlich testen (siehe Testen).
Hilfestellung
Klicken Sie auf die folgenden Tipps, um einige Ratschläge zu erhalten. Versuchen Sie aber zunächst, selbst so weit wie möglich zu kommen.
Ordner und Dateien anlegen
Öffnen Sie VS CodeVisual Studio Code, der kostenlose Code-Editor von Microsoft, in dem Sie im Kurs programmieren. Glossar → entsprechend Ihrem Setup, klicken Sie auf Ihr Terminalfenster und führen Sie cd aus. Die EingabeaufforderungDas Zeichen am Anfang der Zeile im Terminal, etwa $ oder me/ $. Es zeigt, dass das Terminal auf Ihren nächsten Befehl wartet. Steht davor ein Ordnername wie me/, befinden Sie sich gerade in diesem Ordner. Glossar → sollte ungefähr so aussehen:
$Legen Sie dann den Ordner an, wechseln Sie hinein und öffnen Sie die beiden Dateien:
mkdir jar
cd jar
code jar.py
code test_jar.pyWo die Zahlen gespeichert werden
Speichern Sie Kapazität und Zahl der Kekse in __init__ in Instanzvariablen mit Unterstrich, etwa self._capacity und self._size. Die Properties capacity und size geben diese Werte dann zurück.
Ohne Unterstrich geht es nicht: self.size = 0 würde versuchen, die Property size zu überschreiben, und Python bricht mit einem AttributeError ab (die Property hat keinen Setter).
Fehler auslösen, Kekse anzeigen
Einen Fehler lösen Sie mit raise aus; der Text in Klammern ist frei wählbar:
if n < 0:
raise ValueError("Cannot deposit a negative number of cookies.")Ob ein Wert ein int ist, prüft isinstance(capacity, int).
Den String aus Regel 7 bekommen Sie ohne Schleife: "🍪" * 3 ergibt "🍪🍪🍪".
Gerüst für test_jar.py
import pytest
from jar import Jar
def test_init():
...
def test_str():
jar = Jar()
assert str(jar) == ""
jar.deposit(1)
assert str(jar) == "🍪"
jar.deposit(11)
assert str(jar) == "🍪🍪🍪🍪🍪🍪🍪🍪🍪🍪🍪🍪"
def test_deposit():
...
def test_withdraw():
...Ob ein Aufruf den erwarteten ValueError auslöst, prüfen Sie mit pytest.raises. Der Test schlägt fehl, wenn im eingerückten Block kein ValueError auftritt:
with pytest.raises(ValueError):
Jar(-5)Testen
Schreiben Sie die Tests Schritt für Schritt in test_jar.py und führen Sie nach jedem Schritt
pytest test_jar.pyaus. Jede Funktion legt mit Jar() oder Jar(10) eine eigene Dose an.
| Testfunktion | Was sie prüft |
|---|---|
test_init | Kapazität einer neuen Dose (Standard 12 und selbst gewählt), size ist 0; ValueError bei ungültiger Kapazität |
test_str | str(jar) zeigt nach einigen deposit-Aufrufen die richtige Zahl Kekse |
test_deposit | size entspricht der Zahl der hineingelegten Kekse; ValueError, wenn die Kapazität überschritten würde |
test_withdraw | size stimmt nach dem Herausnehmen; ValueError, wenn mehr Kekse herausgenommen werden sollen, als drin sind |
Um withdraw zu testen, müssen erst Kekse in der Dose sein. Rufen Sie dafür im Test einfach vorher deposit auf. Die Aufruffolge aus dem Beispiel eignet sich als Vorlage.
Korrektheit
Führen Sie in Ihrem Terminal den folgenden Befehl aus, um die Korrektheit Ihrer Arbeit zu überprüfen. Testen Sie Ihr Programm aber zuerst selbst.
check50 -l inf-zone/exercises/2026/jarStyle
Führen Sie den folgenden Befehl aus, um den Stil Ihres Codes mit style50Prüfprogramm von CS50, das zeigt, wo Ihr Code von den Formatierungsregeln abweicht. In Grün zeigt es, was Sie ergänzen sollten, in Rot, was wegfallen soll. Glossar → zu analysieren:
style50 jar.pyAbgeben
Geben Sie im Ordner jar ab:
inf upload jarDanach sehen Sie, welche Tests Ihr Programm besteht und ob die Übung für die Bonuspunkte zählt. Wie Sie inf installieren und sich anmelden, steht unter Abgeben mit inf.
Zum Weiterlesen: Methoden isoliert testen
Für die Lösung der Aufgabe nicht nötig.
Methoden zu testen ist oft aufwendiger als eigenständige Funktionen, weil Methoden den Zustand des Objekts (seine Instanzvariablen) verändern. Um withdraw zu testen, rufen Sie vorher deposit auf. Ist aber deposit fehlerhaft, schlägt womöglich auch der Test von withdraw fehl, obwohl withdraw richtig ist.
Deshalb simulieren Programmierer beim Testen den Zustand oft mit sogenannten Mock-Objekten. Mit Werkzeugen wie Pythons Mock-Objektbibliothek setzen sie den Zustand einer Instanz direkt, ohne eine andere Methode aufzurufen, und testen so jede Methode für sich.
Diese Seite als Markdown: ansehen herunterladen