Ebben a cikkben egy szorzótábla alkalmazást fog készíteni a Python objektumorientált programozásának (OOP) erejének felhasználásával.
Gyakorolni fogod az OOP főbb fogalmait, és azt, hogyan használd őket egy teljesen működőképes alkalmazásban.
A Python egy többparadigmás programozási nyelv, ami azt jelenti, hogy mi fejlesztőként minden helyzetre és problémára kiválaszthatjuk a legjobb megoldást. Amikor objektum-orientált programozásról beszélünk, az elmúlt évtizedek egyik leggyakrabban használt paradigmájára utalunk a méretezhető alkalmazások létrehozására.
Tartalomjegyzék
Az OOP alapjai
Gyorsan áttekintjük a Python OOP legfontosabb fogalmát, az osztályokat.
Az osztály egy sablon, amelyben meghatározzuk az objektumok szerkezetét és viselkedését. Ez a sablon lehetővé teszi, hogy példányokat hozzunk létre, amelyek nem más, mint az osztály összetételét követő egyedi objektumok.
Egy egyszerű könyvosztály a cím és a szín attribútumaival a következőképpen határozható meg.
class Book: def __init__(self, title, color): self.title = title self.color = color
Ha példányokat akarunk létrehozni az osztálykönyvből, meg kell hívnunk az osztályt, és argumentumokat kell átadnunk neki.
# Instance objects of Book class blue_book = Book("The blue kid", "Blue") green_book = Book("The frog story", "Green")
Jelenlegi programunkat jól reprezentálná:
A félelmetes dolog az, hogy amikor ellenőrizzük a blue_book és a green_book példányok típusát, a „Könyv” szöveget kapjuk.
# Printing the type of the books print(type(blue_book)) # <class '__main__.Book'> print(type(green_book)) # <class '__main__.Book'>
Miután ezek a koncepciók kristálytiszták, elkezdhetjük építeni a projektet 😃.
Projekt nyilatkozat
Fejlesztői/programozói munka közben az idő nagy részét nem kódírással tölti az újságverem csak az időnk egyharmadát töltjük kódírással vagy újrafeldolgozással.
A másik kétharmadot azzal töltöttük, hogy elolvassuk mások kódját, és elemezzük a problémát, amelyen dolgozunk.
Tehát ehhez a projekthez generálok egy problémanyilatkozatot, és elemezzük, hogyan hozhatjuk létre az alkalmazásunkat. Ennek eredményeként a teljes folyamatot elkészítjük, a megoldás gondolkodásától a kóddal történő alkalmazásig.
Egy általános iskolai tanár szeretne egy játékot, amellyel tesztelheti a 8 és 10 év közötti diákok szorzási készségeit.
A játéknak élet- és pontrendszerrel kell rendelkeznie, ahol a tanuló 3 élettel kezd, és el kell érnie egy bizonyos mennyiségű pontot, hogy nyerjen. A programnak „vesztés” üzenetet kell mutatnia, ha a tanuló egész életét kimeríti.
A játéknak két móddal kell rendelkeznie: véletlenszerű szorzás és asztali szorzás.
Az elsőnek 1-től 10-ig véletlenszerű szorzást kell adnia a tanulónak, és helyesen kell válaszolnia, hogy pontot nyerjen. Ha ez nem történik meg, a diák elveszít egy élőt, és a játék folytatódik. A tanuló csak akkor nyer, ha eléri az 5 pontot.
A második módban egy 1-től 10-ig terjedő szorzótáblát kell megjeleníteni, ahol a tanulónak be kell írnia a megfelelő szorzás eredményét. Ha a tanuló 3-szor bukik, veszít, de ha két asztalt teljesít, akkor a játék véget ér.
Tudom, hogy a követelmények talán kicsit nagyobbak, de ígérem, hogy ebben a cikkben megoldjuk őket 😁.
Oszd meg és uralkodj
A programozás legfontosabb készsége a problémamegoldás. Ennek az az oka, hogy tervet kell készítenie, mielőtt elkezdi feltörni a kódot.
Mindig azt javaslom, hogy vegyük a nagyobb problémát, és osszuk fel kisebbekre, amelyek mindketten könnyen és hatékonyan megoldhatók.
Tehát ha játékot kell létrehoznia, kezdje azzal, hogy fel kell bontania a legfontosabb részeire. Ezeket a részproblémákat sokkal könnyebb lesz megoldani.
Ekkor világossá válik, hogyan kell végrehajtani és integrálni mindent kóddal.
Tehát készítsünk egy grafikont arról, hogyan nézne ki a játék.
Ez a grafika létrehozza az alkalmazásunk objektumai közötti kapcsolatokat. Mint látható, a két fő objektum a véletlenszerű szorzás és a táblázat szorzása. És az egyetlen dolog, amit megosztanak, az a Pontok és Életek tulajdonságai.
Mindezeket az információkat szem előtt tartva, menjünk bele a kódba.
A Szülőjáték osztály létrehozása
Amikor objektum-orientált programozással dolgozunk, a kódismétlődés elkerülésének legtisztább módját keressük. Ezt nevezik SZÁRAZ (ne ismételd magad).
Megjegyzés: Ez a cél nem a kevesebb kódsor írására vonatkozik (a kód minőségét nem szabad ezzel a szemponttal mérni), hanem a leggyakrabban használt logika elvonatkoztatására.
Az előző elképzelés szerint alkalmazásunk szülőosztályának kell kialakítania a másik két osztály szerkezetét és kívánt viselkedését.
Lássuk, hogyan készülne.
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} livesn") def print_current_score(self): print(f"nYour score is {self.points}") def print_description(self): print("nn" + self.description.center(self.message_lenght) + "n") # Basic run method def run(self): self.print_welcome_message() self.print_description()
Hú, ez elég nagy osztálynak tűnik. Hadd magyarázzam el mélyen.
Először is ismerjük meg az osztályattribútumokat és a konstruktort.
Az osztályattribútumok alapvetően az osztályon belül, de a konstruktoron vagy bármely metóduson kívül létrehozott változók.
Míg a példányattribútumok csak a konstruktoron belül létrehozott változók.
A fő különbség a kettő között a hatókör. azaz az osztályattribútumok elérhetők egy példány objektumból és az osztályból is. Másrészt a példányattribútumok csak egy példányobjektumból érhetők el.
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
Egy másik cikk mélyebbre merülhet ebben a témában. Maradjon kapcsolatban, hogy elolvashassa.
A get_numeric_input függvény arra szolgál, hogy megakadályozza, hogy a felhasználó olyan bemenetet adjon meg, amely nem numerikus. Amint azt észreveheti, ez a módszer arra szolgál, hogy megkérdezze a felhasználót, amíg nem kap numerikus bevitelt. Később a gyerek óráin használjuk.
A nyomtatási módszerek lehetővé teszik, hogy elmentsük azt az ismétlődést, hogy ugyanazt a nyomtatást minden alkalommal, amikor egy esemény történik a játékban.
Végül, de nem utolsósorban, a futtatási metódus csak egy burkoló, amelyet a Véletlenszerű szorzás és a Táblázat szorzás osztályok használnak a felhasználóval való interakcióhoz, és mindent működőképessé tesznek.
A gyermek osztályok létrehozása
Miután létrehoztuk azt a szülőosztályt, amely meghatározza az alkalmazásunk szerkezetét és néhány funkcióját, itt az ideje a tényleges játékmód osztályok létrehozásának az öröklődés erejével.
Véletlenszerű szorzási osztály
Ez az osztály fogja futtatni játékunk „első módját”. Természetesen a random modult fogja használni, ami lehetővé teszi számunkra, hogy 1-től 10-ig véletlenszerű műveleteket kérjünk a felhasználótól. Itt egy remek cikk a véletlenszerű modulokról (és más fontos modulokról) 😉.
import random # Module for random operations
class RandomMultiplication(BaseGame): description = "In this game you must answer the random multiplication correctlynYou 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 correctn") # Adds a point self.points += 1 else: print("nSorry, your answer is incorrectn") # 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()
Íme egy újabb hatalmas óra 😅. De ahogy korábban is mondtam, nem a sorok számától függ, hanem az, hogy mennyire olvasható és hatékony. A Pythonban pedig az a legjobb, hogy lehetővé teszi a fejlesztők számára, hogy tiszta és olvasható kódot készítsenek, mintha normál angolul beszélnének.
Ezen az órán van egy dolog, ami megzavarhatja, de a lehető legegyszerűbben elmagyarázom.
# 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)
A gyerekosztály konstruktora meghívja a szuper függvényt, amely egyben a szülő (BaseGame) osztályra is utal. Alapvetően ezt mondja a Pythonnak:
Töltsd ki a szülőosztály „nyertes_pontok” attribútuma 5-tel!
Nem szükséges self-et tenni a super().__init__() részbe csak azért, mert a konstruktor belsejében super-t hívunk, és az redundáns lesz.
A futási metódusban a szuper függvényt is használjuk, és látni fogjuk, mi történik abban a kódrészletben.
# 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() .....
Ahogy észreveheti a futtatási metódust a szülőosztályban, nyomtassa ki az üdvözlő és leíró üzenetet. De jó ötlet megtartani ezt a funkciót, és továbbiakat is hozzáadni a gyermekosztályokhoz. Ennek megfelelően a super-t használjuk a szülő metódus összes kódjának futtatására a következő darab futtatása előtt.
A futtatási funkció másik része meglehetősen egyszerű. Számot kér a felhasználótól a művelet üzenetével, amelyre válaszolnia kell. Ezután az eredményt összehasonlítjuk a valós szorzással, és ha egyenlők, akkor hozzáad egy pontot, ha nem vesz fel 1 életet.
Érdemes elmondani, hogy while-else ciklusokat használunk. Ez meghaladja a cikk kereteit, de néhány napon belül közzéteszek egyet róla.
Végül a get_random_numbers a random.randint függvényt használja, amely egy véletlenszerű egész számot ad vissza a megadott tartományon belül. Ezután két véletlenszerű egész szám sorát adja vissza.
Véletlenszerű szorzási osztály
A „második mód”-nak szorzótábla formátumban kell megjelenítenie a játékot, és meg kell győződnie arról, hogy a felhasználó legalább 2 táblázatra helyesen válaszol.
Ebből a célból ismét felhasználjuk a super képességét, és a szülőosztály point_to_win attribútuma 2-re módosítja.
class TableMultiplication(BaseGame): description = "In this game you must resolve the complete multiplication table correctlynYou 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()
Mint látható, csak ennek az osztálynak a futtatási metódusát módosítjuk. Ez az öröklődés varázsa, egyszer leírjuk azt a logikát, amit több helyen is használunk, és elfelejtjük 😅.
A futtatási metódusban egy for ciklust használunk, hogy megkapjuk a számokat 1-től 10-ig, és felépítettük a műveletet, amely megjelenik a felhasználó számára.
Ha az életek kimerülnek, vagy elérik a nyeréshez szükséges pontokat, a while hurok ismét megszakad, és megjelenik a nyer vagy veszít üzenet.
IGEN, létrehoztuk a játék két módját, de eddig semmi sem fog történni, ha futtatjuk a programot.
Tehát véglegesítsük a programot úgy, hogy végrehajtjuk a módválasztást, és a választástól függően példányosítjuk az osztályokat.
Választás megvalósítása
A felhasználó kiválaszthatja, hogy melyik módban szeretne játszani. Lássuk tehát, hogyan kell megvalósítani.
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()
Először is megkérjük a felhasználót, hogy válasszon az 1 vagy a 2 mód közül. Ha a bemenet nem érvényes, a szkript leáll. Ha a felhasználó az első módot választja, a program a Véletlenszerű szorzás játékmódot, ha pedig a másodikat választja, a Táblázat szorzás módot futtatja.
Íme, hogyan nézne ki.
Következtetés
Gratulálok, te csak Python alkalmazás létrehozása objektum-orientált programozással.
Az összes kód elérhető a Github adattár.
Ebben a cikkben megtanulta:
- Használjon Python osztályú konstruktorokat
- Hozzon létre egy funkcionális alkalmazást az OOP segítségével
- Használja a szuper függvényt a Python osztályokban
- Alkalmazza az öröklődés alapfogalmait
- Osztály- és példányattribútumok megvalósítása
Boldog kódolást 👨💻
Ezután fedezze fel a legjobb Python IDE-t a jobb termelékenység érdekében.