• Erledigen Sie die Anwendungssicherheit auf die richtige Weise! Erkennen, schützen, überwachen, beschleunigen und mehr…
  • In diesem Artikel erstellen Sie eine  Multiplikationstabellen Appmithilfe der objektorientierten Programmierung (OOP) in Python.

    Sie üben die Hauptkonzepte von OOPund wie man sie in einer voll funktionsfähigen Anwendung verwendet.

    Python ist eine Multiparadigma-Programmiersprache, was bedeutet, dass wir als Entwickler für jede Situation und jedes Problem die beste Option auswählen können. Wenn wir über objektorientierte Programmierung sprechen, beziehen wir uns auf eines der am häufigsten verwendeten Paradigmen zum Erstellen skalierbarer Anwendungen in den letzten Jahrzehnten.

    Die Grundlagen von OOP

    Wir werden einen kurzen Blick auf das wichtigste Konzept von OOP in werfen Python, die Klassen.

    A Klasse ist eine Vorlage, in der wir die Struktur und das Verhalten von Objekten definieren. Mit dieser Vorlage können wir erstellen InstanzenDies sind nichts anderes als einzelne Objekte, die nach der Zusammensetzung der Klasse erstellt wurden.

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

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

    Wenn wir Instanzen des Klassenbuchs erstellen möchten, müssen wir die Klasse aufrufen und übergeben Argumente verbunden.

    # Instance objects of Book class
    blue_book = Book("The blue kid", "Blue")
    green_book = Book("The frog story", "Green")

    Eine gute Darstellung unseres aktuellen Programms wäre:

    Class.png

    Das Tolle ist, wenn wir den Typ des überprüfen blaues Buch and grünes Buch  In einigen Fällen erhalten wir "Buch".

    # Printing the type of the books
    
    print(type(blue_book))
    # <class '__main__.Book'>
    print(type(green_book))
    # <class '__main__.Book'>

    Nachdem diese Konzepte glasklar sind, können wir mit dem Aufbau des Projekts beginnen 😃.

    Projektaussage

    Während der Arbeit als Entwickler / Programmierer wird laut die meiste Zeit kein Code geschrieben dann neu stapeln Wir verbringen nur ein Drittel unserer Zeit damit, Code zu schreiben oder umzugestalten.

    Wir haben die anderen zwei Drittel damit verbracht, den Code anderer zu lesen und Analyse des Problems wir arbeiten an.

    Für dieses Projekt werde ich eine Problembeschreibung erstellen und analysieren, wie unsere App daraus erstellt wird. Infolgedessen machen wir den gesamten Prozess, indem wir über die Lösung nachdenken, um sie mit Code anzuwenden.

    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 Leben 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 Meldung „verlieren“ anzeigen, wenn der Schüler sein ganzes Leben lang erschöpft ist.

    Das Spiel muss zwei Modi haben, zufällige Multiplikationen und Tabellenmultiplikationen.

    Der erste sollte dem Schüler eine zufällige Multiplikation von 1 bis 10 geben, und er muss richtig antworten, um einen Punkt zu gewinnen. Wenn das nicht passiert, verliert der Schüler ein Leben und das Spiel geht weiter. Der Schüler gewinnt nur, wenn er 5 Punkte erreicht.

    Der zweite Modus muss eine Multiplikationstabelle von 1 bis 10 anzeigen, in die der Schüler das Ergebnis der jeweiligen Multiplikation eingeben muss. Wenn der Schüler dreimal versagt, verliert er / sie, aber wenn er / sie zwei Tische abschließt, endet das Spiel.

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

    Teile und herrsche

    Die wichtigste Fähigkeit beim Programmieren ist das Lösen von Problemen. Dies liegt daran, dass Sie einen Plan haben müssen, bevor Sie beginnen können Hacking im Code.

    Ich schlage immer vor, das größere Problem in kleinere zu unterteilen, die sowohl einfach als auch effizient gelöst werden können.

    Wenn Sie also ein Spiel erstellen müssen, teilen Sie es zunächst in die wichtigsten Teile auf. Diese Unterprobleme werden viel einfacher zu lösen sein.

    In diesem Moment haben Sie die Klarheit, wie Sie alles ausführen und in Code integrieren können.

    Machen wir also ein Diagramm, wie das Spiel aussehen würde.

    teilen und erobern.png

    Diese Grafik stellt die Beziehungen zwischen den Objekten unserer App her. Wie Sie sehen können, sind die beiden Hauptobjekte Zufällige Multiplikation and Tabellenmultiplikation. Und das einzige, was sie teilen, sind die Attribute Punkte and Lebt.

    Lassen Sie uns mit all diesen Informationen in den Code einsteigen.

    Erstellen der übergeordneten Spielklasse

    Wenn wir mit objektorientierter Programmierung arbeiten, suchen wir nach dem saubersten Weg, um Code-Wiederholungen zu vermeiden. Das nennt man TROCKEN (Wiederhole dich nicht).

    Hinweis: Dieses Ziel bezieht sich nicht darauf, weniger Codezeilen zu schreiben (die Codequalität darf nicht an diesem Aspekt gemessen werden), sondern darauf, die am häufigsten verwendeten zu abstrahieren Logik.

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

    Mal sehen, wie es gemacht wird.

    class BaseGame:
    
        # Lenght which the message is centered
        message_lenght = 60
        
        description = ""    
            
        def __init__(self, points_to_win, n_lives=3):
            """Base game class
    
            Args:
                points_to_win (int): the points the game will need to be finished 
                n_lives (int): The number of lives the student have. Defaults to 3.
            """
            self.points_to_win = points_to_win
    
            self.points = 0
            
            self.lives = n_lives
    
        def get_numeric_input(self, message=""):
    
            while True:
                # Get the user input
                user_input = input(message) 
                
                # If the input is numeric, return it
                # If it isn't, print a message and repeat
                if user_input.isnumeric():
                    return int(user_input)
                else:
                    print("The input must be a number")
                    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"CONGRATULATION YOU REACHED {self.points}".center(self.message_lenght))
            
        def print_current_lives(self):
            print(f"Currently you have {self.lives} lives\n")
    
        def print_current_score(self):
            print(f"\nYour score is {self.points}")
    
        def print_description(self):
            print("\n\n" + self.description.center(self.message_lenght) + "\n")
    
        # Basic run method
        def run(self):
            self.print_welcome_message()
            
            self.print_description()

    Wow, das scheint eine ziemlich große Klasse zu sein. Lassen Sie es mich ausführlich erklären.

    Lassen Sie uns zunächst das verstehen Klassenattribute und der Konstruktor.

    Base-Game-Konstruktor.png

    Grundsätzlich gilt, Klassenattributesind Variablen, die innerhalb der Klasse, aber außerhalb des Konstruktors oder einer beliebigen Methode erstellt werden.

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

    Der Hauptunterschied zwischen diesen beiden ist der Umfang. Das heißt, auf Klassenattribute kann sowohl von einem Instanzobjekt als auch von der Klasse aus zugegriffen werden. Auf Instanzattribute kann hingegen nur von einem Instanzobjekt aus zugegriffen werden.

    game = BaseGame(5)
    
    # Accessing game message lenght class attr from class
    print(game.message_lenght) # 60
    
    # Accessing the message_lenght class attr from class
    print(BaseGame.message_lenght)  # 60
    
    # Accessing the points instance attr from instance
    print(game.points) # 0
    
    # Accesing the points instance attribute from class
    print(BaseGame.points) # Attribute error
    

    Ein anderer Artikel kann tiefer in dieses Thema eintauchen. Bleiben Sie in Kontakt, um es zu lesen.

    Das get_numeric_input Die Funktion wird verwendet, um zu verhindern, dass der Benutzer Eingaben bereitstellt, die nicht numerisch sind. Wie Sie vielleicht bemerken, dient diese Methode dazu, den Benutzer zu fragen, bis er eine numerische Eingabe erhält. Wir werden es später in den Klassen des Kindes verwenden.

    Base-Game-input.png

    Der Druck Methoden Erlauben Sie uns, die Wiederholung des Druckens jedes Mal zu speichern, wenn ein Ereignis im Spiel auftritt.

    Zu guter Letzt die Lauf Methode ist nur ein Wrapper, den die Zufällige Multiplikation and Tabellenmultiplikation Klassen werden verwendet, um mit dem Benutzer zu interagieren und alles funktionsfähig zu machen.

    Base-game-run.png

    Klassen des Kindes erstellen

    Sobald wir diese übergeordnete Klasse erstellt haben, die die Struktur und einige Funktionen unserer App festlegt, ist es an der Zeit, die eigentlichen Spielmodusklassen mithilfe der Leistung von zu erstellen Erbschaft.

    Zufällige Multiplikationsklasse

    Diese Klasse wird den "ersten Modus" unseres Spiels ausführen. Es wird die verwenden zufällig Modul natürlich, das uns die Möglichkeit gibt, den Benutzer nach zufälligen Operationen von 1 bis 10 zu fragen. ist ein ausgezeichneter Artikel über das Zufallsprinzip (und andere wichtige Module) 😉.

    import random # Module for random operations
    class RandomMultiplication(BaseGame):
    
        description = "In this game you must answer the random multiplication correctly\nYou win if you reach 5 points, or lose if you lose all your lives"
    
        def __init__(self):
            # The numbers of points needed to win are 5
            # Pass 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):
            
            # Call the upper class to print the welcome messages
            super().run()
            
    
            while self.lives > 0 and self.points_to_win > self.points:
                # Gets two random numbers
                number1, number2 = self.get_random_numbers()
    
                operation = f"{number1} x {number2}: "
    
                # Asks the user to answer that operation 
                # Prevent value errors
                user_answer = self.get_numeric_input(message=operation)
    
                if user_answer == number1 * number2:
                    print("\nYour answer is correct\n")
                    
                    # Adds a point
                    self.points += 1
                else:
                    print("\nSorry, your answer is incorrect\n")
    
                    # Substracts a live
                    self.lives -= 1
                
                self.print_current_score()
                self.print_current_lives()
                
            # Only get executed when the game is finished
            # And none of the conditions are true
            else:
                # Prints the final message
                
                if self.points >= self.points_to_win:
                    self.print_win_message()
                else:
                    self.print_lose_message()
    

    Hier ist eine weitere massive Klasse 😅. Aber wie ich bereits sagte, ist es nicht die Anzahl der Zeilen, sondern die Lesbarkeit und Effizienz. Und das Beste an Python ist, dass Entwickler sauberen und lesbaren Code erstellen können, als würden sie normales Englisch sprechen.

    Diese Klasse hat eine Sache, die Sie verwirren kann, aber ich werde es so einfach wie möglich erklären.

        # Parent class
        def __init__(self, points_to_win, n_lives=3):
            "...
        # Child class
        def __init__(self):
            # The numbers of points needed to win are 5
            # Pass 5 "points_to_win" argument
            super().__init__(5)

    Das Konstruktor der Kinderklasse ruft die groß Funktion, die gleichzeitig auf die übergeordnete Klasse (BaseGame) verweist. Es sagt Python im Grunde:

    Füllen Sie das Attribut "points_to_win" der übergeordneten Klasse mit 5 aus!

    Es ist nicht notwendig zu setzen selbst, innerhalb der  super().__init__() Teil nur, weil wir super innerhalb des Konstruktors aufrufen, und es würde zu redundanten führen.

    Wir benutzen auch die groß Funktion in der run-Methode, und wir werden sehen, was in diesem Teil des Codes passiert.

        # Basic run method
        # Parent method
        def run(self):
            self.print_welcome_message()
            
            self.print_description()
        def run(self):
            
            # Call the upper class to print the welcome messages
            super().run()
            
            .....

    Wenn Sie die Ausführungsmethode in der übergeordneten Klasse bemerken, drucken Sie die Begrüßungs- und Beschreibungsnachricht. Es ist jedoch eine gute Idee, diese Funktionalität beizubehalten und zusätzliche Funktionen in die untergeordneten Klassen aufzunehmen. Demnach verwenden wir groß um den gesamten Code der übergeordneten Methode auszuführen, bevor das nächste Stück ausgeführt wird.

    Der andere Teil der Ausführungsfunktion ist ziemlich einfach. Der Benutzer wird nach einer Nummer mit der Meldung der Operation gefragt, auf die er antworten muss. Dann wird das Ergebnis mit der realen Multiplikation verglichen und wenn sie gleich sind, wird ein Punkt hinzugefügt, wenn sie nicht 1 Leben abnehmen.

    Es ist erwähnenswert, dass wir while-else-Schleifen verwenden. Dies geht über den Rahmen dieses Artikels hinaus, aber ich werde in einigen Tagen einen darüber veröffentlichen.

    Schließlich get_random_numbers, nutzt die Funktion random.randint, die eine zufällige Ganzzahl innerhalb des angegebenen Bereichs zurückgibt. Dann wird ein Tupel aus zwei zufälligen ganzen Zahlen zurückgegeben.

    Zufällige Multiplikationsklasse

    Der „zweite Modus“ muss das Spiel in einem Multiplikationstabellenformat anzeigen und sicherstellen, dass der Benutzer mindestens 2 Tische richtig beantwortet.

    Zu diesem Zweck werden wir wieder die Kraft von nutzen groß und ändern Sie das übergeordnete Klassenattribut points_to_win um 2.

    class TableMultiplication(BaseGame):
    
        description = "In this game you must resolve the complete multiplication table correctly\nYou win if you solve 2 tables"
        
        def __init__(self):
            # Needs to complete 2 tables to win
            super().__init__(2)
    
        def run(self):
    
            # Print welcome messages
            super().run()
    
            while self.lives > 0 and self.points_to_win > self.points:
                # Gets two random numbers
                number = random.randint(1, 10)            
    
                for i in range(1, 11):
                    
                    if self.lives <= 0:
                        # Ensure that the game can't continue 
                        # if the user depletes the lives
    
                        self.points = 0
                        break 
                    
                    operation = f"{number} x {i}: "
    
                    user_answer = self.get_numeric_input(message=operation)
    
                    if user_answer == number * i:
                        print("Great! Your answer is correct")
                    else:
                        print("Sorry your answer isn't correct") 
    
                        self.lives -= 1
    
                self.points += 1
                
            # Only get executed when the game is finished
            # And none of the conditions are true
            else:
                # Prints the final message
                
                if self.points >= self.points_to_win:
                    self.print_win_message()
                else:
                    self.print_lose_message()

    Wie Sie sehen, ändern wir nur die Ausführungsmethode 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 abzurufen und die Operation zu erstellen, die dem Benutzer angezeigt wird.

    Noch einmal, wenn die Leben erschöpft sind oder die zum Gewinnen erforderlichen Punkte erreicht sind, wird die while-Schleife unterbrochen und die Gewinn- oder Verlustmeldung wird angezeigt.

    JA, wir haben die beiden Modi des Spiels erstellt, aber bis jetzt wird nichts passieren, wenn wir das Programm ausführen.

    Lassen Sie uns das Programm abschließen, indem Sie die Modusauswahl implementieren und die Klassen abhängig von dieser Auswahl instanziieren.

    Auswahl Implementierung

    Der Benutzer kann auswählen, welcher Modus abgespielt werden soll. Mal sehen, wie man es implementiert.

    if __name__ == "__main__":
    
        print("Select Game mode")
    
        choice = input("[1],[2]: ")
    
        if choice == "1":
            game = RandomMultiplication()
        elif choice == "2":
            game = TableMultiplication()
        else:
            print("Please, select a valid game mode")
            exit()
    
        game.run()

    Zunächst bitten wir den Benutzer, zwischen 1 und 2 Modi zu wählen. Wenn die Eingabe nicht gültig ist, wird das Skript nicht mehr ausgeführt. Wenn der Benutzer den ersten Modus auswählt, führt das Programm den aus Zufällige Multiplikation Spielmodus, und wenn er / sie den zweiten auswählt, wird der Tabellenmultiplikation Modus wird ausgeführt.

    So würde es aussehen.

    game.png

    Fazit

    Herzlichen Glückwunsch, Sie gerade Erstellen Sie eine Python-App mit objektorientierter Programmierung.

    Der gesamte Code ist in der verfügbar Github-Repository.

    In diesem Artikel haben Sie gelernt:

    • Verwenden Sie Python-Klassenkonstruktoren
    • Erstellen Sie eine funktionale App mit OOP
    • Verwenden Sie die Superfunktion in Python-Klassen
    • Wenden Sie die Grundkonzepte der Vererbung an
    • Implementieren Sie Klassen- und Instanzattribute

    Viel Spaß beim Codieren 👨‍💻

    Als nächstes erkunden Sie einige der beste Python IDE für eine bessere Produktivität.