Geekflare wird von unserem Publikum unterstützt. Es kann sein, dass wir durch den Kauf von Links auf dieser Seite Affiliate-Provisionen verdienen.
Unter Entwicklung Zuletzt aktualisiert: September 23, 2023
Weitergeben:
Invicti Web Application Security Scanner - die einzige Lösung, die eine automatische Überprüfung von Schwachstellen mit Proof-Based Scanning™ ermöglicht.

In diesem Artikel werden Sie eine Anwendung für das Einmaleins erstellen, indem Sie die Möglichkeiten der objektorientierten Programmierung (OOP) in Python nutzen

Sie werden die wichtigsten Konzepte der O.O.P. kennenlernen und erfahren, wie Sie diese in einer voll funktionsfähigen Anwendung einsetzen können

Python ist eine multiparadigmatische Programmiersprache, was bedeutet, dass wir als Entwickler für jede Situation und jedes Problem die beste Option wählen können. Wenn wir von objektorientierter Programmierung sprechen, beziehen wir uns auf eines der in den letzten Jahrzehnten am häufigsten verwendeten Paradigmen zur Erstellung skalierbarer Anwendungen

Die Grundlagen von OOP

Werfen wir einen kurzen Blick auf das wichtigste Konzept der O.O.P in Python: die Klassen

Eine Klasse ist eine Vorlage, in der wir die Struktur und das Verhalten von Objekten definieren. Diese Vorlage ermöglicht es uns, Instanzen zu erstellen, die nichts anderes als individuelle Objekte sind, die nach der Zusammensetzung der Klasse erstellt werden

Eine einfache Buchklasse mit den Attributen Titel und Farbe würde wie folgt definiert werden

class Book:
 def __init__(self, title, color):
 self.title = title
 self.color = color

Wenn wir Instanzen der Klasse Book erstellen wollen, müssen wir die Klasse aufrufen und ihr Argumente übergeben
#

 Instanzobjekte der Klasse Book
blue_book = Book("Das blaue Kind", "Blau")
green_book = Book("Die Froschgeschichte", "Grün")

Eine gute Darstellung unseres aktuellen Programms wäre

Class.png

Das Tolle ist, dass wir, wenn wir den Typ der Instanzen von blue_book und green_book überprüfen, “Book” erhalten
#

 Drucken des Typs der Bücher

print(type(blue_book))

#

<class '__main__.Book'>
print(type(green_book))

#

<class '__main__.Book'&gt

Nachdem wir uns über diese Konzepte im Klaren sind, können wir mit der Erstellung des Projekts beginnen 😃

Projekt-Anweisung

Wenn wir als Entwickler/Programmierer arbeiten, verbringen wir die meiste Zeit nicht mit dem Schreiben von Code. Laut thenewstack verbringen wir nur ein Drittel unserer Zeit mit dem Schreiben oder Refactoring von Code

Die anderen zwei Drittel verbringen wir damit, den Code anderer zu lesen und das Problem zu analysieren, an dem wir gerade arbeiten

Für dieses Projekt werde ich also eine Problemstellung erstellen und wir werden analysieren, wie wir daraus unsere App erstellen können. So machen wir den kompletten Prozess durch, vom Nachdenken über die Lösung bis zur Anwendung mit Code

Ein Grundschullehrer möchte ein Spiel, um die Multiplikationsfähigkeiten von Schülern im Alter von 8 bis 10 Jahren zu testen.

Das Spiel muss ein Lebens- und ein Punktesystem haben, bei dem der Schüler mit 3 Leben beginnt und eine bestimmte Anzahl von Punkten erreichen muss, um zu gewinnen. Das Programm muss eine “Verloren”-Meldung anzeigen, wenn der Schüler alle seine Leben aufgebraucht hat.

Das Spiel muss über zwei Modi verfügen: Zufallsmultiplikationen und Tabellenmultiplikationen.

Im ersten Modus muss der Schüler eine zufällige Multiplikation von 1 bis 10 erhalten, die er richtig beantworten muss, um einen Punkt zu gewinnen. Wenn das nicht der Fall ist, verliert der Schüler einen Punkt und das Spiel geht weiter. Der Schüler gewinnt erst, wenn er/sie 5 Punkte erreicht hat.

Im zweiten Modus wird eine Multiplikationstabelle von 1 bis 10 angezeigt, in die der Schüler das Ergebnis der jeweiligen Multiplikation eingeben muss. Wenn der Schüler 3 Mal scheitert, verliert er/sie, aber wenn er/sie zwei Tabellen vervollständigt, ist das Spiel beendet

Ich weiß, dass die Anforderungen vielleicht ein wenig größer sind, aber ich verspreche Ihnen, dass wir sie in diesem Artikel lösen werden 😁

Teilen und erobern

Die wichtigste Fähigkeit beim Programmieren ist das Lösen von Problemen. Sie müssen nämlich einen Plan haben, bevor Sie anfangen, sich in den Code einzuhacken

Ich schlage immer vor, ein größeres Problem zu nehmen und es in kleinere Probleme zu unterteilen, die sowohl einfach als auch effizient gelöst werden können

Wenn Sie also ein Spiel entwickeln müssen, beginnen Sie damit, es in die wichtigsten Teile zu zerlegen. Diese Teilprobleme werden viel leichter zu lösen sein

Erst dann haben Sie Klarheit darüber, wie Sie alles mit Code ausführen und integrieren können

Lassen Sie uns also eine Grafik erstellen, wie das Spiel aussehen würde

divide and conquer.png

Diese Grafik stellt die Beziehungen zwischen den Objekten unserer App her. Wie Sie sehen können, sind die beiden Hauptobjekte die Zufallsmultiplikation und die Tabellenmultiplikation. Und das einzige, was sie gemeinsam haben, sind die Attribute Punkte und Leben

Mit all diesen Informationen im Hinterkopf können wir nun mit dem Code beginnen

Erstellen der Klasse Parent game

Wenn wir mit objektorientierter Programmierung arbeiten, suchen wir nach dem saubersten Weg, um Codewiederholungen zu vermeiden. Das nennt man DRY (don’t repeat yourself)

Hinweis: Dieses Ziel hat nichts damit zu tun, möglichst wenige Codezeilen zu schreiben (die Codequalität darf nicht an diesem Aspekt gemessen werden), sondern die am häufigsten verwendete Logik zu abstrahieren

Gemäß der vorherigen Idee muss die übergeordnete Klasse unserer Anwendung die Struktur und das gewünschte Verhalten der beiden anderen Klassen festlegen

Lassen Sie uns sehen, wie das geht

class BaseGame:

 # Länge, um die die Nachricht zentriert ist
 message_lenght = 60
    
 description = ""
        
 def __init__(self, points_to_win, n_lives=3):
 """Base game class

 Args:
 points_to_win (int): die Punkte, die das Spiel benötigt, um beendet zu werden
 n_lives (int): Die Anzahl der Leben, die der Schüler hat. Der Standardwert ist 3.
 """
 self.points_to_win = points_to_win

 self.points = 0
        
 self.lives = n_lives

 def get_numeric_input(self, message=""):

 while True:
 # Holen Sie die Benutzereingabe
 user_input = input(message)
            
 # Wenn die Eingabe numerisch ist, geben Sie sie zurück
 # Wenn nicht, geben Sie eine Meldung aus und wiederholen Sie
 if user_input.isnumeric():
 return int(user_input)
 else:
 print("Die Eingabe muss eine Zahl sein")
 continue
             
 def print_welcome_message(self):
 print("PYTHON MULTIPLICATION GAME".center(self.message_lenght))

 def print_lose_message(self):
 print("SORRY YOU LOST ALL OF YOUR LIVES".center(self.message_lenght))

 def print_win_message(self):
 print(f "HERZLICHEN GLÜCKWUNSCH SIE HABEN {self.points}".center(self.message_lenght))
        
 def print_current_lives(self):
 print(f "Sie haben derzeit {self.leben} Leben\n")

 def print_current_score(self):
 print(f"\nIhr Punktestand ist {self.points}")

 def print_description(self):
 print("\n\n" self.description.center(self.message_lenght) "\n")

 # Grundlegende Laufmethode
 def run(self):
 self.print_welcome_message()
        
 self.print_description()

Wow, das scheint eine ziemlich große Klasse zu sein. Lassen Sie mich das genauer erklären

Zunächst einmal müssen wir die Klassenattribute und den Konstruktor verstehen

Base-game-constructor.png

Grundsätzlich sind Klassenattribute Variablen, die innerhalb der Klasse, aber außerhalb des Konstruktors oder einer Methode erstellt werden

Während Instanzattribute Variablen sind, die nur innerhalb des Konstruktors erstellt werden

Der Hauptunterschied zwischen diesen beiden ist der Geltungsbereich, d.h. Klassenattribute sind sowohl von einem Instanzobjekt als auch von der Klasse aus zugänglich. Auf Instanzattribute hingegen kann nur von einem Instanzobjekt aus zugegriffen werden

game = BaseGame(5)

#

Zugriff auf game message lenght class attr from class
print(game.message_lenght) # 60

#

Zugriff auf die message_lenght class attr from class
print(BaseGame.message_lenght) # 60

#

Zugriff auf die points instance attr from instance
print(game.points) # 0

#

Zugriff auf das points instance attribute from class
print(BaseGame.points) # Attribute error

Ein weiterer Artikel kann dieses Thema vertiefen. Bleiben Sie in Kontakt, um ihn zu lesen

Die Funktionget_numeric_input wird verwendet, um zu verhindern, dass der Benutzer Eingaben macht, die nicht numerisch sind. Wie Sie vielleicht bemerken, ist diese Methode so konzipiert, dass sie den Benutzer so lange fragt, bis sie eine numerische Eingabe erhält. Wir werden sie später in den Klassen des Kindes verwenden

Base-game-input.png

Mit den print-Methoden können wir uns die Wiederholung des Ausdrucks bei jedem Ereignis im Spiel sparen

Zu guter Letzt ist die run-Methode nur ein Wrapper, der von den Klassen Zufallsmultiplikation und Tabellenmultiplikation verwendet wird, um mit dem Benutzer zu interagieren und alles funktionsfähig zu machen

Base-game-run.png

Erstellen der Klassen des Kindes

Nachdem wir die übergeordnete Klasse erstellt haben, die die Struktur und einen Teil der Funktionalität unserer Anwendung festlegt, ist es an der Zeit, die eigentlichen Spielmodusklassen zu erstellen, indem wir die Macht der Vererbung nutzen

Klasse für Zufallsmultiplikation

Diese Klasse wird den “ersten Modus” unseres Spiels ausführen. Sie wird natürlich das Zufallsmodul verwenden, das uns die Möglichkeit gibt, dem Benutzer Zufallsoperationen von 1 bis 10 vorzuschlagen. Hier ist ein ausgezeichneter Artikel über das random (und andere wichtige Module) 😉

import random # Modul für Zufallsoperationen
class RandomMultiplication(BaseGame):

 description = "In diesem Spiel müssen Sie die Zufallsmultiplikation richtig beantworten\Sie gewinnen, wenn Sie 5 Punkte erreichen, oder verlieren, wenn Sie alle Ihre Leben verlieren"

 def __init__(self):
 # Die zum Gewinnen benötigte Punktzahl ist 5
 # Übergeben Sie 5 "points_to_win" Argument
 super().__init__(5)

 def get_random_numbers(self):

 first_number = random.randint(1, 10)
 second_number = random.randint(1, 10)

 return first_number, second_number
        
 def run(self):
        
 # Ruft die obere Klasse auf, um die Willkommensnachrichten zu drucken
 super().run()
        

 while self.lives > 0 and self.points_to_win > self.points:
 # Ermittelt zwei Zufallszahlen
 number1, number2 = self.get_random_numbers()

 operation = f"{number1} x {number2}: "

 # Fordert den Benutzer auf, diese Operation zu beantworten
 # Verhindert Wertefehler
 user_answer = self.get_numeric_input(message=operation)

 if user_answer == number1 * number2:
 print("\nIhre Antwort ist richtig\n")
                
 # Fügt einen Punkt hinzu
 self.points = 1
 else:
 print("\nSorry, your answer is incorrect\n")

 # Subtrahiert ein Leben
 self.leben -= 1
            
 self.print_current_score()
 self.print_current_lives()
            
 # Wird nur ausgeführt, wenn das Spiel beendet ist
 # Und keine der Bedingungen erfüllt ist
 else:
 # Druckt die letzte Nachricht
            
 if self.points >= self.points_to_win:
 self.print_win_message()
 else:
 self.print_lose_message()

Hier ist eine weitere umfangreiche Klasse 😅. Aber wie ich schon sagte, es geht nicht um die Anzahl der Zeilen, sondern darum, wie lesbar und effizient sie ist. Und das Beste an Python ist, dass es Entwicklern erlaubt, sauberen und lesbaren Code zu erstellen, als ob sie normales Englisch sprechen würden

Diese Klasse hat eine Sache, die Sie vielleicht verwirrt, aber ich werde sie so einfach wie möglich erklären

 # Elternklasse
 def __init__(self, points_to_win, n_lives=3):
 

...
 # Kindklasse
 def __init__(self):
 # Die Anzahl der Punkte, die zum Gewinnen benötigt werden, beträgt 5
 # Übergeben Sie 5 "points_to_win" Argumente
 super().__init__(5)

Der Konstruktor der Kindklasse ruft die Superfunktion auf, die sich gleichzeitig auf die Elternklasse (BaseGame) bezieht. Damit wird Python im Grunde gesagt
Fülle

das Attribut “points_to_win” der Elternklasse mit 5!

Es ist nicht notwendig, self in den super().__init__() -Teil einzufügen, nur weil wir super innerhalb des Konstruktors aufrufen, und das würde zu einer Überschneidung führen

Wir verwenden die super-Funktion auch in der run-Methode und wir werden sehen, was in diesem Teil des Codes passiert
#

 Grundlegende run-Methode
 # Übergeordnete Methode
 def run(self):
 self.print_welcome_message()
        
 self.print_description()
 def run(self):
        
 # Aufruf der oberen Klasse, um die Willkommensnachrichten zu drucken
 super().run()
        
....

Wie Sie vielleicht bemerken, druckt die run-Methode in der übergeordneten Klasse die Begrüßungs- und Beschreibungsnachricht aus. Es ist jedoch eine gute Idee, diese Funktionalität beizubehalten und auch in den untergeordneten Klassen zusätzliche Funktionen hinzuzufügen. Dementsprechend verwenden wir super , um den gesamten Code der übergeordneten Methode auszuführen, bevor wir den nächsten Teil ausführen

Der andere Teil der Ausführungsfunktion ist ziemlich einfach. Sie fragt den Benutzer nach einer Zahl mit der Nachricht der Operation, die er beantworten muss. Dann wird das Ergebnis mit der realen Multiplikation verglichen und wenn sie gleich sind, wird ein Punkt hinzugefügt, wenn sie nicht gleich sind, wird 1 Leben abgezogen

Es ist erwähnenswert, dass wir while-else-Schleifen verwenden. Das würde den Rahmen dieses Artikels sprengen, aber ich werde in ein paar Tagen einen Artikel darüber veröffentlichen

Schließlich verwendet get_random_numbers die Funktion random.randint, die eine zufällige ganze Zahl innerhalb des angegebenen Bereichs zurückgibt. Dann gibt sie ein Tupel aus zwei zufälligen Ganzzahlen zurück

Klasse für zufällige Multiplikation

Der “zweite Modus” muss das Spiel in Form einer Multiplikationstabelle anzeigen und sicherstellen, dass der Benutzer mindestens 2 Tabellen richtig beantwortet

Zu diesem Zweck nutzen wir wieder die Macht von super und ändern das Attribut points_to_win der Elternklasse auf 2

class TableMultiplication(BaseGame):

 description = "In diesem Spiel müssen Sie die komplette Multiplikationstabelle richtig auflösen. Sie gewinnen, wenn Sie 2 Tabellen lösen"
    
 def __init__(self):
 # Muss 2 Tabellen vervollständigen, um zu gewinnen
 super().__init__(2)

 def run(self):

 # Druckt Willkommensnachrichten
 super().run()

 while self.lives > 0 and self.points_to_win > self.points:
 # Ermittelt zwei Zufallszahlen
 number = random.randint(1, 10)

 for i in range(1, 11):
                
 if self.lives <= 0:
 # Sicherstellen, dass das Spiel nicht fortgesetzt werden kann
 # wenn der Benutzer die Leben verbraucht

 self.points = 0
 break
                
 operation = f"{number} x {i}: "

 user_answer = self.get_numeric_input(message=operation)

 if user_answer == Zahl * i:
 print("Toll! Ihre Antwort ist richtig")
 else:
 print("Leider ist Ihre Antwort nicht richtig")

 self.lives -= 1

 self.punkte = 1
            
 # Wird nur ausgeführt, wenn das Spiel beendet ist
 # Und keine der Bedingungen erfüllt ist
 else:
 # Druckt die letzte Nachricht
            
 if self.points >= self.points_to_win:
 self.print_win_message()
 else:
 self.print_lose_message()

Wie Sie sehen können, ändern wir nur die Run-Methode dieser Klasse. Das ist die Magie der Vererbung, wir schreiben einmal die Logik, die wir an mehreren Stellen verwenden, und vergessen sie 😅

In der Run-Methode verwenden wir eine for-Schleife, um die Zahlen von 1 bis 10 zu erhalten und die Operation zu erstellen, die dem Benutzer angezeigt wird

Wenn die Leben aufgebraucht sind oder die zum Gewinnen benötigten Punkte erreicht sind, bricht die while-Schleife ab und die Nachricht über Sieg oder Niederlage wird angezeigt

YEAH, wir haben die beiden Modi des Spiels erstellt, aber bis jetzt passiert nichts, wenn wir das Programm ausführen

Lassen Sie uns also das Programm abschließen, indem wir die Wahl des Modus implementieren und die Klassen instanziieren, die von dieser Wahl abhängen

Implementierung der Auswahl

Der Benutzer kann wählen, welchen Modus er spielen möchte. Schauen wir uns also an, wie man das implementiert

if __name__ == "__main__":

 print("Spielmodus auswählen")

 choice = input("[1],[2]: ")

 if choice == "1":
 game = RandomMultiplication()
 elif choice == "2":
 game = TableMultiplication()
 else:
 print("Bitte wählen Sie einen gültigen Spielmodus aus")
 exit()

 game.run()

Zunächst bitten wir den Benutzer, zwischen den Modi 1 oder 2 zu wählen. Wenn die Eingabe ungültig ist, wird das Skript nicht weiter ausgeführt. Wenn der Benutzer den ersten Modus auswählt, führt das Programm den Spielmodus Zufallsmultiplikation aus, und wenn er den zweiten auswählt, wird der Modus Tabellenmultiplikation ausgeführt

So würde es aussehen

game.png

Fazit

Herzlichen Glückwunsch, Sie haben gerade eine Python-Anwendung mit objektorientierter Programmierung erstellt

Der gesamte Code ist im Github-Repository verfügbar

In diesem Artikel haben Sie gelernt,

  • Python-Klassenkonstruktoren verwenden
  • Eine funktionale Anwendung mit OOP erstellen
  • Die Superfunktion in Python-Klassen zu verwenden
  • Die grundlegenden Konzepte der Vererbung anzuwenden
  • Klassen- und Instanzattribute zu implementieren

Viel Spaß beim Programmieren 👨‍💻

Als Nächstes lernen Sie einige der besten Python-IDEs für mehr Produktivität kennen.

  • Daniel Diaz
    Autor
Dank an unsere Sponsoren
Weitere gute Lektüre zum Thema Entwicklung
Energie für Ihr Unternehmen
Einige der Tools und Dienste, die Ihr Unternehmen beim Wachstum unterstützen.
  • Invicti nutzt das Proof-Based Scanning™, um die identifizierten Schwachstellen automatisch zu überprüfen und innerhalb weniger Stunden verwertbare Ergebnisse zu erzielen.
    Versuchen Sie Invicti
  • Web Scraping, Residential Proxy, Proxy Manager, Web Unlocker, Search Engine Crawler und alles, was Sie zum Sammeln von Webdaten benötigen.
    Versuchen Sie Brightdata
  • Monday.com ist ein All-in-One-Betriebssystem, mit dem Sie Projekte, Aufgaben, Arbeit, Vertrieb, CRM, Arbeitsabläufe und vieles mehr verwalten können.
    Versuch Montag
  • Intruder ist ein Online-Schwachstellen-Scanner, der Schwachstellen in Ihrer Infrastruktur aufspürt, um kostspielige Datenschutzverletzungen zu vermeiden.
    Versuchen Sie Intruder