Modellierung eines Kassensystems

Die Modellierung des Kassensystems beginnt mit der Anschauung und Beschreibung des Problemfeldes.

Kassierer und Kassierinnen am Warenband scannen die Preise der Waren eines Einkaufs. Wenn die Eingabe abgeschlossen ist, nennen sie den Gesamtpreis und fordern sie die Kundschaft zum Bezahlen auf. Sie nehmen das Geld in Empfang, öffnen die Kasse und sortieren die Geldeinheiten in die richtigen Fächer. Bei Überbezahlung wird unmittelbar anschließend aus denselben Fächern das Wechselgeld entnommen und der Kundschaft zurückgegeben. Dann folgt der nächste Kunde.

Abb. 3: Schematische Darstellung des Ablaufs beim Kassieren.

Der Ablauf beim Kassieren wird durch das durchlaufende Warenband vorgegeben:

  • In einem äußeren Kreislauf wechseln die Kunden; jeder neue Kunde wird nach derselben Routine bedient.
  • In einem inneren Kreislauf werden zu jedem Kunden die Waren auf dem Band erfasst und es wird der Gesamtpreis errechnet.

Die Situation an der Kasse kann man daher in vier Bestandteile auflösen: Den Kassierer, die Kasse, das (Geld-)Fach und das Geld. Von der Ware interessiert den Kassierer eigentlich nur der Preis.

Abb. 4: Modell der Situation an der Kasse.

Zur objektorientierten Implementierung des Modells sind die Klassen KASSIERER, KASSE, FACH und GELD vorstellbar. Vgl. Abbildung 4. Die Abbildung veranschaulicht, wie jede Klasse mindestens ein Objekt der folgenden Klasse enthält.

Projektziele

Wenn die folgenden Ziele erreicht sind, soll die Kassensituation als realistisch abgebildet gelten und das Ende des Projekts ist erreicht.

  1. Der digitale Kassierer verfügt über eine Menge an Geldstücken und Geldscheinen, etwa 10 x 1Cent, 10 x 2 Cent usw.
  2. Eingegebene Warenpreise werden summieren.
  3. Nach Abschluss der Summenbildung wird um die Eingabe eines möglichst passenden Geldbetrags gebeten und das nötige Wechselgeld errechnet.
  4. Wenn das Kleingeld in der Kasse nicht für das Wechselgeld ausreicht, wird der Kunde aufgefordert mit der Karte zu zahlen.
  5. Optional: Ist es möglich, eine digitale Währung mit einer Art Seriennummer einzuführen?

Weiter: Implementierung I: Daten und Datenstrukturen >>

Der Fall „Kassierer“

„Puh!“, ächzt der Mann hinter dem Tisch am Ladenausgang, „Ständig diese Rechnerei mit der Preisen! Und dann immer wieder das Wechselgeld: Wenn es nicht schon Registrierkassen mit Warenscanner gäbe, müsste man die glatt erfinden.“ Naja. Das ist doch kein Problem. Sie wünschen, wir erfinden: Herzlich willkommen zum Fall „Kassierer“.

Abb. 1: Registrierkasse, Pixabay.

Die Registrierkasse wurde gegen Ende des 19. Jahrhunderts erfunden. Zentrale Idee war es ursprünglich, dass sich die Schublade mit den Geldfächern nur beim Kassieren der Waren öffnete und dadurch den Diebstahl von Kleingeld verhinderte oder zumindest erschwerte. Seit den Anfängen haben Elektronik und digitale Technik die Kassen sehr verändert. Sie dienen nun nicht mehr nur der Aufbewahrung von Geld, sondern können auch jeden Einkauf, also jeden Geschäftsabschluss dokumentieren. Daher haben Kassensysteme heute eine zentrale Funktion in der Gastronomie oder im Einzelhandel auch im Hinblick auf die Umsatzsteuer und es gibt eigens formulierte Grundsätze des Bundesministeriums für Finanzen, wie die dabei entstehenden Daten zu behandeln sind.

Abb. 2: Fächer mit Wechselgeld, Pixabay.

Zu Übungszwecken soll hier ein Kassensystem nachprogrammiert werden. Die Arbeitsweise im Projekt beginnt mit der Modellierung und wendet sich dann bottomup der Erstellung der Programmskripte zu. Der Fall „Kassierer“ besteht damit aus vier Teilen:

  1. Modellierung eines Kassensystems
  2. Implementierung I: Daten und Datenstrukturen
  3. Implementierung II: Operationen und Berechnungen
  4. Implementierung III: Steuerung und Interface

Weiter: Modellierung eines Kassensystems >>

Creative Commons Lizenzvertrag Dieses Werk ist lizenziert unter einer Creative Commons Namensnennung 4.0 International Lizenz.

23 Der Zwerg nimmt Gestalt an.

Die Klasse ZWERG ist als Wesen der Konsole schon recht eigen, verfügt er doch über einen Namen, eine Alter und eine Größe. Nun soll er noch ein Aussehen, eine Gestalt bekommen.

Abb. 1: Das vereinfachte Aussehen des Zwergs.

Wie in Abbildung 1 zu erkennen ist, besteht das Bild des ZWERGs aus einem Körper, einem Kopf und einem Hut. Man kann das modellieren, indem man die Klasse ZWERG aus den Klassen HUT, KOPF und KOERPER zusammensetzt. Das nennt man Komposition: Die Klasse ZWERG hat / enthält ein Objekt der Klasse HUT, ein Objekt der Klasse KOPF und ein Objekt der Klasse KOERPER.

Abb. 2.: Detailliertes Klassendiagramm der Klasse ZWERG

Zur Implementierung dieser „Komposition“ werden drei weitere Attribute der Klasse ZWERG angelegt (self.hut, self.kopf, self.koerper) und mit geeigneten Objekten belegt.

Aufgabe

  1. Welche Eigenschaften müssten die Klassen HUT, KOPF und KOERPER haben, damit sie als Gestalt angezeigt werden können?
  2. Welche Methode müssten die Klassen HUT, KOPF und KOERPER haben, damit sie angezeigt werden können? Wie könnte man diese Methode mit den Mitteln der Turtle implementieren?

22 Aufstrebender Zwerg

Zwerge verändern sich. Sie werden nicht nur älter, sondern sie nehmen auch an Einsicht und Körpergröße zu. Lassen wir mal die Einsicht beiseite.

Aufgabe

Der Zwerg soll seine Größe verändern können.

  1. Implementiere eine Methode wachse(), bei der die Größe bei jedem Aufruf um die Eigenschaft self.wachstum zunimmt.
  2. Der Zwerg soll mit jedem Jahr, das er altert, auch um self.wachstum größer werden.
  3. Zwerge bleiben aber in der Regel recht klein. Daher soll die Methode wachse() unterscheiden: [1] Bei einem Alter bis 40 soll die Größe um self.wachstum zunehmen. [2] Bei einem Alter zwischen 40 und 60 soll er gleich groß bleiben. [3] Ab 60 Jahren soll der Zwerg um die Hälfte von self.wachstum kleiner werden.

Entwicklertipps

Aufgabe 1: Die Methode wachse() funktioniert sehr ähnlich wie die Methode altere(). Aufgabe 2: Es ist besser, die Fähigkeiten der Methoden altere() und wachse() nicht grundsätzlich zu ändern. Aber die eine Methode kann intern die andere aufrufen. Aufgabe 3: Die Methode wachse() braucht eine if-Abfrage, die drei Fälle unterscheidet.

Ampelprojekt – Phase 3: Programmierung

Dem Aufbau des Modells folgt die abstrakte Modellierung, die Beschreibung der Ampel mit Methoden der Informatik. Das ist die Voraussetzung für die Implementierung als Programm.

Einfache Ausgaben – Testprogramm A

Zunächst soll der Aufbau getestet werden. Gelingt es eine LED an- und auszuschalten?

import RPi.GPIO as GPIO, time

print("""
==========================
==    TEST 1 LED        ==
==========================""")

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW)    #aa gr
GPIO.setup(10, GPIO.OUT, initial=GPIO.LOW)   #aa g
GPIO.setup(12, GPIO.OUT, initial=GPIO.LOW)   #aa r

GPIO.setup(3, GPIO.OUT, initial=GPIO.LOW)    #fa r
GPIO.setup(5, GPIO.OUT, initial=GPIO.LOW)    #fa gr

GPIO.output(8, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(8, GPIO.LOW)
time.sleep(0.5)

print("done.")

Testprogramm B

Gelingt es alle LEDs an- und auszuschalten?

import RPi.GPIO as GPIO, time

def onoff(pin, t):  # (***)
    GPIO.output(pin, GPIO.HIGH)
    time.sleep(t)
    GPIO.output(pin, GPIO.LOW)
    time.sleep(t)

print("""
==========================
==    TEST alle LEDs    ==
==========================""")

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW)    #aa gr
GPIO.setup(10, GPIO.OUT, initial=GPIO.LOW)   #aa g
GPIO.setup(12, GPIO.OUT, initial=GPIO.LOW)   #aa r

GPIO.setup(3, GPIO.OUT, initial=GPIO.LOW)    #fa r
GPIO.setup(5, GPIO.OUT, initial=GPIO.LOW)    #fa gr

liste = [8,10,12,3,5] # (*)

for led in liste:     # (**)
    onoff(led, 0.5)

print("done.")

Das Programm B unterscheidet sich in drei Punkten von Programm A: Eine Liste enthält alle Pins (*) und wird in einer Schleife abgearbeitet (**). In der Schleife wird eine Funktion aufgerufen, die auf einen Pin Strom gibt und ihn wieder abschaltet (***).

Video 5: Testprogramm B, Ampel 01

Abfrage von Eingaben an Tastern

Das Ampelsystem ändert seinen Zustand nach dem Drücken des Knopfes an einer der beiden Ampeln. Diese Zustandsänderung soll immer verfügbar sein, d.h. sie soll immer wieder ausgelöst werden können.

Abbildung 7: Zustandsdiagramm – Zustandsübergang ausgelöst durch Drücken der Taste an der Ampel.

Um den Zustandsübergang von Zustand 1 zu Zustand 2 auszulösen, braucht das Ampelsystem eine Eingabemöglichkeit ähnlich der echten Ampel: Wenn ein bestimmter Knopf gedrückt wird, schaltet die Ampel um. Der Übergang von Zustand 2 zu Zustand 1 erfolgt dagegen zeitgesteuert: Wenn die Fußgänger genug Zeit hatten, um die Ampel zu überqueren, wird das Signallicht zurückgestellt.

Programm 02 führt dazu drei Änderungen ein. Zentral ist die Endlosschleife (*) mit der Abfrage (**) der Pins 16 bzw. 18. Als Grundlage dafür werden die beiden Pins 16 und 18 als Eingaben konfiguriert (***).

import RPi.GPIO as GPIO, time

#===============================#
# FUNCTION                      #

def onoff(pin, t):
    GPIO.output(pin, GPIO.HIGH)
    time.sleep(t)
    GPIO.output(pin, GPIO.LOW)
    time.sleep(t)

#===============================#
# CONFIG / SETUP                #

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

lights = [8,    # autoampel gruen
          10,   # aa gelb
          12,   # aa rot
          3,    # fussgaengerampel rot   
          5     # fa gruen
          ]

for led in lights:
    GPIO.setup(led, GPIO.OUT, initial=GPIO.LOW)

GPIO.setup(16, GPIO.IN) # input 1     (***)
GPIO.setup(18, GPIO.IN) # input 2

#===============================#    
# HAUPTPRG                      #

print("""prg: ampel 02
==========================
==    TEST              ==
==========================""")

while True:                              # (*)
    if GPIO.input(16) or GPIO.input(18): # (**)
        for led in lights:
            onoff(led, 0.5)

Die Endlosschleife bewirkt, dass die nachfolgende Abfrage immer wieder geprüft wird. Im Effekt werden jedes Mal nach dem Drücken des ersten oder des zweiten Tasters alles LEDs einmal durchgeschaltet. Im Vergleich mit der fertigen Ampel fehlt jetzt noch die Logik der Signale.

Video 6: Programm Ampel 02

Bedingte Signalschaltung

Programm 03 bringt die Endlosschleife, die Abfrage der Pins und die bedingte Ausführung der Funktionen fussgaenger() bzw. autofahrer() in eine logische Folge. Dabei stellt die Funktion fussgaenger() Zustand 2 her (*), die Funktion autofahrer() stellt danach zeitbedingt Zustand 1 her (**).

Video 6: Programm Ampel 03
import RPi.GPIO as GPIO, time

#==============================================#
# CONFIG / SETUP                               #

# globale Variablen: verfuegbare Pins
aa_gruen =  8 # Output: LEDs
aa_gelb  = 10
aa_rot   = 12
fa_rot   =  3
fa_gruen =  5

in_1     = 16 # Input: Taster
in_2     = 18

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

GPIO.setup(aa_gruen, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(aa_gelb,  GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(aa_rot,   GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(fa_rot,   GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(fa_gruen, GPIO.OUT, initial=GPIO.LOW)

GPIO.setup(in_1, GPIO.IN) # input 1
GPIO.setup(in_2, GPIO.IN) # input 2

#==============================================#
# FUNKTIONEN                                   #

def fussgaenger():
    # fussgaenger rot und autofahrer gruen
    GPIO.output(fa_rot, GPIO.HIGH)
    GPIO.output(aa_gruen, GPIO.HIGH)
    time.sleep(3)
    # autofahrer gelb
    GPIO.output(aa_gruen, GPIO.LOW)
    GPIO.output(aa_gelb, GPIO.HIGH)
    time.sleep(3)
    # autofahrer rot
    GPIO.output(aa_gelb, GPIO.LOW)
    GPIO.output(aa_rot, GPIO.HIGH)
    time.sleep(3)        
    # fussgaenger gruen
    GPIO.output(fa_rot, GPIO.LOW)
    GPIO.output(fa_gruen, GPIO.HIGH)    

def autofahrer():
    # fussgaenger rot
    GPIO.output(fa_gruen, GPIO.LOW)
    GPIO.output(fa_rot, GPIO.HIGH)
    time.sleep(3)        
    # autofahrer rot und gelb
    GPIO.output(aa_gelb, GPIO.HIGH)
    time.sleep(3)
    # autofahrer gruen
    GPIO.output(aa_gelb, GPIO.LOW)
    GPIO.output(aa_rot, GPIO.LOW)
    GPIO.output(aa_gruen, GPIO.HIGH)

def aus():
    GPIO.output(fa_rot, GPIO.LOW)
    GPIO.output(aa_gruen, GPIO.LOW)

#==============================================#  
# HAUPTPRG                                     #

print("""
================================================
==   PROGRAMM AMPEL 03                        ==
================================================
""")

while True:
    
    aus()
    
    if GPIO.input(in_1) or GPIO.input(in_2):
        # autoampel auf rot; fussgaenger gruen
        fussgaenger()     # (*)
        # zwischenzeit
        time.sleep(10)
        # autoampel auf gruen; fussgaenger rot
        autofahrer()      # (**)
        time.sleep(10)
            

Ampelprojekt – Phase 2: Aufbau des Modells

Das Modell des Straßenübergangs mit Fußgängerampel besteht aus der Basisplatte, den einzelnen elektronischen Teilen, dem Raspberry Pi und der Programmierung. Auf der Basisplatte werden alle Teile montiert und die LEDs, Widerstände und Kabel verlötet. Die Elektronik wird anschließend mit den Pins des Raspberry Pi verbunden.

Basisplatte

Die Basisplatte kann aus Sperrholz, Pappe oder ähnlichen Materialien gefertigt werden. Sie dient zu Befestigung der Ampeln. Im Grunde könnte man auch eine Steckplatine verwenden.

Abbildung 5: Skizze zum Aufbau des Modells

Mit Leim oder Heißkleber lassen sich die einzelnen Schichten fixieren. Die Ampeln können auch von unten durch die Basisplatte gesteckt und befestigt werden. Der entsprechende Durchlasss in der Mitte der Platte wird am Ende durch das Tonpapier für die Straße verschlossen.

Verkabelung

Nach dem Zusammenbau müssen die Kabelverbindungen verlötet werden.

Abbildung 6: Schaltplan der LEDs, Widerstände und Taster

Bei der Schaltung muss beachtet werden, dass jede LED durch einen Widerstand abgesichert ist. Beim Anschluss an den Raspberry Pi sollten 100 Ohm genügen. Oftmals liest man, dass 220 oder 330 Ohm verwendet werden.

Der Taster wird zusammen mit einem Pulldown-Widerstand angeschlossen. Beim Aktivieren des Tasters erzeugt das später einen Stromeingang, der von der Programmierschnittstelle des Raspberry Pi als Wert 1 erkannt wird.

Die Ampeln im Detail

Die einzelnen Ampeln wurden von der Unterseite der Platte mit Heißkleber fixiert und mit dünnen mehradrigen Kabelbändern verbunden. Die Kathoden der LEDs werden mit dem Schutzwiderstand verbunden. Die Taster wurden wegen der Stabilität auf ein kleines Platinenstück gelötet und dort mit dem Pulldown-Widerstand beschaltet. Alle Kabel werden zunächst auf die Unterseite der Basisplatte und von dort vor dem Raspberry Pi nach oben geführt. Die Steckverbindung zum Raspberry Pi lässt sich lösen, damit man den Einplatinenrechner mehrfach verwenden kann.

Weiter: Programmierung >>

Ampelprojekt – Phase 1: Testaufbau

Testaufbau am Steckbrett

Um sich dem Ampelsystem anzunähern wird zunächst eine Testschaltung aufgebaut. Dabei werden einzelne LEDs mit Pins des Raspberry verbunden und jeweils mit einem Schutzwiderstand von 100 Ohm abgesichert.

Abbildung 3: Schaltplan des Testaufbaus

Programmierung

Zunächst zeigt Programm 01, ob grundlegende Konzepte funktionieren: Läuft der Raspberry Pi? Funktioniert der Anschuss der Pins an das Steckbrett? Sind die Teile alle ganz?

import RPi.GPIO as GPIO
import time

print("prgO1.py")

# KONFIGURATION / SETUP
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
# Eine rote LED wird am physikalischen Pin 16 angeschlossen.
GPIO.setup(16, GPIO.OUT, initial=GPIO.LOW)

# LICHT AN / AUS
GPIO.output(16, GPIO.HIGH)    # "Rot an!"
time.sleep(0.5)               # 0,5 Sek. warten
GPIO.output(16, GPIO.LOW)     # "Rot aus!"

Am schnellsten erstellt man das Programm auf dem Raspberry Pi selbst mit der Python IDLE oder einem vorinstallierten Editor.

Programm 02 führt eine einfache For-Schleife ein, und zeigt damit, dass der elektronische Output fortlaufend wiederholbar ist. Das ist insofern wichtig, als die spätere Ampel selbstständig laufen soll und nicht nur dann, wenn die Maus auf der OS-Oberfläche des Raspberry Pi das Programm startet.

Video 2: Programm 02
import RPi.GPIO as GPIO
import time

print("prgO2.py")

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(16, GPIO.OUT, initial=GPIO.LOW)

for n in range(5):
    print("Durchgang: "+str(n+1))

    GPIO.output(16, GPIO.HIGH)
    print("rot an")
    time.sleep(1)
    GPIO.output(16, GPIO.LOW)
    print("rot aus")
    time.sleep(1)

Programm 03 zeigt, wie LEDs im Wechsel an- und ausgeschaltet werden können. Die Ampel folgt dann später dem typischen Phasenmodell, erfordert also über den reinen Wechsel hinaus noch die Logik der Signalabfolge.

Video 03: Programm 03
import RPi.GPIO as GPIO
import time

print("prgO3.py")
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT, initial=GPIO.LOW) #gelb
GPIO.setup(13, GPIO.OUT, initial=GPIO.LOW) #rot

for n in range(5):
    print("Durchgang: "+str(n+1))
    GPIO.output(11, GPIO.HIGH)
    GPIO.output(13, GPIO.LOW)
    print('gelb')
    time.sleep(1)
    GPIO.output(11, GPIO.LOW)
    GPIO.output(13, GPIO.HIGH)
    print('rot')
    time.sleep(1)
    
# alles aus
GPIO.output(11, GPIO.LOW)
GPIO.output(13, GPIO.LOW)

Phasen einer Ampel

Ampeln für den Straßenverkehr mit drei Signalleuchten schalten in Phasen nach immer derselben Logik.

Abbildung 4: Traffic lights 4 states; public domain, eingebettet von Wikimedia Commons.

Programm 04 setzt die Phasenschaltung der Verkehrsampel in einem imperativen Python-Skript um.

Video 4: Programm 04
import RPi.GPIO as GPIO, time

print("prgO4.py")
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(10, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(12, GPIO.OUT, initial=GPIO.LOW)
GPIO.output(8, GPIO.HIGH)
GPIO.output(10, GPIO.LOW)
GPIO.output(12, GPIO.LOW)
time.sleep(1)
GPIO.output(10, GPIO.HIGH)
time.sleep(1)
GPIO.output(8, GPIO.LOW)
GPIO.output(10, GPIO.LOW)
GPIO.output(12, GPIO.HIGH)
time.sleep(10)
GPIO.output(12, GPIO.LOW)

Weiter: Modell >>

Ampelprojekt mit dem Raspberry Pi

Abbildung 1: Im Vordergrund mittig die Ampel für Autofahrer und Fußgänger, etwas rechts davon der Taster zum Anfordern des Signals. Im Hintergrund rechts der Raspberry Pi4 mit dunklem Miuzei-Gehäuse.

Die Ampel ist ein beliebtes Beispiel im Informatikunterricht zur Zustandsmodellierung. In diesem Beitrag wird ausgehend von einem Raspberry Pi ein Ampelmodell entwickelt und programmiert. Das Projekt wird in drei Phasen entwickelt:

Voraussetzungen

Die Basis bildet der Raspberry Pi. Er ist mit Python einfach zu programmieren, verfügt über eine gute Anschlussfähigkeit dank der GPIO-Pins und über einen HDMI-Ausgang, den man beim Einsatz im Unterricht mit einer Dokumentenkamera oder direkt mit einem Beamer verbinden kann. Eine USB-Tastatur und Maus oder eine Bluetooth Multimedia-Tastatur ergänzen die Hardware. Geladen wird als Betriebssystem Rasberry Pi OS (früher Raspian). Das OS lässt sich frei herunterladen und auf eine Micro-SD-Karte schreiben. Kleine Ampeln lassen sich mit dem 3D-Drucker herstellen. Vorlagen gibt es zum Beispiel bei Thingiverse. Alternativ gibt es fertige Ampeln zum Bestellen. LEDs, Taster und Widerstände sind nicht besonders teuer und können bei verschiedenen Anbietern über das Internet bestellt werden.

Ziel

Abbildung 2: Die gesamte Ampelanlage.

Die gesamte Ampelanlage ist auf ein Sperrholzbrett montiert, die Straße aus Tonpapier ausgeschnitten und aufgeklebt. Die Verdrahtung erfolgt auf der Unterseite des Brettes: Die beiden Ampel für die Autofahrer sind parallel geschaltet, ebenso die Ampel für die Fußgänger. Es gibt zwei Taster, die mit einem Pull-Down-Widerstand als Input zur Anforderung des Fußgängersignals funktionieren. Programmierseitig werden sie mit einer ODER-Logik verbunden.

Video 1: Das fertige Ampelmodell

Weiter: Testaufbau am Steckbrett >>

Creative Commons Lizenzvertrag Dieses Werk ist lizenziert unter einer Creative Commons Namensnennung 4.0 International Lizenz.

21 Ein Zwerg

Objektorientierung heißt virtuelles Leben im Rechner betrachten. Stellen wir uns einen vereinfachten Basiszwerg mit wenigen Eigenschaften vor:

Basiszwerg. Bild: Pixabay, CC0.
  • Name, z.B. „Hugo“ – der Datentyp ist eine Zeichenkette, also ein String, abgekürzt str,
  • Alter, z.B. 31 – der Datentyp ist eine Ganzzahl, also ein Integer, abgekürzt int,
  • Größe, z.B. 48,5 – der Datentyp ist eine Kommazahl, also Float.

Der Zwerg verfüge über zwei Methoden. Er kann

  • altern und
  • sich vorstellen.

Aufgabe 1:

Instanziere ein virtuelles Objekt der Klasse ZWERG und rufe anschließend zum Test die Methode stelle_dich_vor() auf.

Aufgabe 2:

Die Zeit bleibt nicht stehen. Selbst für Zwerge nicht. Mit jedem Aufruf einer Methode altere() soll der Zwerg um ein Jahr altern.

  • Implementiere die Methode altere(), indem du sie zur Klasse ZWERG hinzufügst. – Orientiere dich dazu an der Art und Weise, wie die Methode stelle_dich_vor() geschrieben wird.
  • Teste die Klasse und die Methode. 

Schlüsselwörter und Besonderheiten

class: Es leitet die Definition einer Klasse ein. Nach class folgt in allen Fällen der Name der Klasse, hier eben ZWERG, in anderen Fällen KREIS, RECHTECK, DREIECK, usw. Klassennamen können frei gewählt werden, solange es nicht Schlüsselwörter sind. Am Ende der Zeile steht ein Doppelpunkt. Alles was zur aktuellen Klasse gehört, wird danach um einen festen Abstand eingerückt.

def: Um eine Funktion oder eine Methode zu definieren dient das Schlüsselwort def. Es folgen der Name der Funktion oder Methode, zwei Klammern und ein Doppelpunkt. Alles was zur aktuellen Definition gehört, wird danach um einen festen Abstand eingerückt.

self: Dieses Wort stellt einen Bezug innerhalb einer Klasse her her. Weil ein Name häufig nur in einem bestimmten Raum, in einem bestimmten Kontext eindeutig ist, bedeutet self soviel wie „dein eigene(r)“. Innerhalb einer Klassendefinition wird daher immer dann self geschrieben, wenn die „eigene“ Eigenschaft oder die „eigene“ Methode gemeint ist. Im oberen Beispiel etwa self.alter oder self.stelle_dich_vor().

__init__: Dieses Wort bezeichnet die Konstruktormethode einer Klasse in Python. Der Konstruktor hat immer denselben Namen.

Links:

20 Das Zwergensystem

Objekte und Systeme von Objekten kann man sehr schön mit Zwergen veranschaulichen; Zwerge im Sinn von Gartenzwergen, im Sinn der Fabelwesen aus dem Herrn der Ringe, der Heinzelmännchen oder ähnlichem.
Warum?
In allen Filmen und Erzählungen sind Zwerge autonome Wesen. Sie haben bestimmte Eigenschaften (Attribute) und verfügen in der Regel über spezielle Fähigkeiten (Methoden). Ein System von Zwergen kann man daher sehr schön objektorientiert modellieren.  Die Darstellung und das Bild folgen dem fiktionalen Rahmen.

Bild: Pixabay, CC0.

Eine Rückübertragung der Vorstellung von Zwergen auf die menschliche Gesellschaft ist hier an keiner Stelle intendiert.