W poprzednich lekcjach, nauczyliśmy się czym jest programowanie obiektowe w Python (OOP), moduły, ale przede wszystkim nauczyliśmy się podstaw języka Python. Czas to wszystko połączyć w całość i wykonać mały, lecz ciekawy projekt / zadanie – organizer. Zaczynajmy!
Zadanie jest proste. Musimy napisać program, który będzie symulować organizer / notes / segregator. A mianowicie:
- Musi mieć możliwość przechowywania notatek oraz wizytówek
- Po uruchomieniu, powinno wyświetlać się menu, które pozwala użytkownikowi: (1) – dodać notatkę (2) – dodać wizytówkę (3) wyświetlić notatki (4) – wyświetlić wizytówki (0) zamknąć organizer, a tym samym zakończyć działanie programu
- Program powinien być podzielony na moduły, czyli plik
Potencjalne rozwiązanie.
na pierwszy rzut oka, mamy 3 różne klasy:
- klasa organizer – która zawiera metody zarządzające jego pracą. Jak dodaj notatkę
- klasa notatka – zawierająca takie elementy jak tytuł oraz treść. Być może priorytet
- klasa wizytówka – zawierająca imię, nazwisko, telefon itd
Klasa organizer
Potencjalnie, nasza klasa mogła by mieć taką strukturę:
class organizer: __właściciel = "" __bazaDanych = [] def __init__(self, właściciel): self.właściciel = właściciel def dodajNotatkę(self): pass def dodajWizytówkę(self): pass def wyświetlNotatki(self): pass def wyświetlWizytówki(self): pass
Czyli spełniała by funkcje, które są w zadaniu. zmienna '__bazaDanych’, jest natomiast listą, która może przechowywać obiekty typu 'notatka’, lub 'wizytówka’. Jak tylko zostaną dodane za pomocą funkcji dodajNotatkę(), oraz dodajWizytówkę(). A funkcje wyświetlNotatki oraz wyświetlWizytówki(), mogą czytać naszą bazę danych i drukować wybrane elementy. Ma to sens.
Klasa notatka oraz wizytówka
Obydwie klasy, mają części wspólne i wydaje się być uzasadnione, aby utworzyć klasę nadrzędną 'przedmiot’, którą będą dziedziczyć, a która będzie dbać, że obydwie klasy, będą podobne.
W przyszłości ułatwi nam to również dodawanie kolejnych przedmiotów. Jedną z rzeczy które chcieli byśmy wymusić, to aby i 'notatka’ i 'wizytówka’, obsługiwały metodę specjalną __str__, która odpowiada za to, aby obiekt mógł być obsłużony funkcją print. Jak print(notatka) czy też print(wizytówka).
Będzie to wielkim ułatwieniem dla metod klasy 'organizator’, które mają wyświetlać notatki i wizytówki. Tym samym klasy te mogą wyglądać następująco:
from abc import ABC, abstractmethod class przedmiot(ABC): def __init__ (self, typ, priorytet): pass @abstractmethod def __str__(self): pass class notatka(przedmiot): def __init__(self, priorytet, tytuł, treść): pass def __str__(self): pass class wizytówka(przedmiot): def __init__(self, priorytet, imię, nazwisko, telefon): pass def __str__(self): pass
Klasa 'notatka’ oraz 'wizytówka’, nadpisują metodę specjalną '__str__’, w której musimy zdefiniować, co chcemy, aby się wyświetlało, jeżeli postanowimy wydrukować naszą klasę, za pomocą print(notatka / wizytówka).
Natomiast, w konstruktorach, trzeba zadbać o wywołanie konstruktora, klasy 'przedmiot, oraz o zainicjowanie pozostałych zmiennych, przekazanych w parametrach.
Tym samym, nasze klasy, mogą przyjąć finalną postać:
from abc import ABC, abstractmethod class przedmiot(ABC): def __init__ (self, typ, priorytet): self.typ = typ self.priorytet = priorytet @abstractmethod def __str__(self): pass class notatka(przedmiot): def __init__(self, priorytet, tytuł, treść): super().__init__("notatka", priorytet) self.tytuł = tytuł self.treść = treść def __str__(self): info = self.typ + "Priorytet " + self.priorytet + "\n" info += self.tytuł + "\n" info += self.treść + "\n" return info class wizytówka(przedmiot): def __init__(self, priorytet, imię, nazwisko, telefon): super().__init__("wizytówka", priorytet) self.imię = imię self.nazwisko = nazwisko self.telefon = telefon def __str__(self): info = self.typ + "Priorytet " + self.priorytet + "\n" info += self.imię + " " + self.nazwisko + "\n" info += self.telefon + "\n" return info
W kolejnym kroku, należy uzupełnić naszą klasę 'organizer’, tak aby metody spełniały swoje zadania.
Klasa organizer.
- Metody 'dodajNotatkę()’ oraz 'dodajWizytówkę()’, muszą odpytywać użytkownika o szczegóły notatek i wizytówek, które użytkownich chce dodać, następnie tworzyć na tej podstawie obiekt i dodać go do naszej bazy danych, którą jest zmienna __bazaDanych.
- Metody 'wyświetlNotatki()’ oraz 'wyśletlWizytówki()’, muszą przeszukiwać naszą bazę danych i drukować odpowiednie obiekty.
i tym samym, nasza klasa 'organizer’, jest gotowa przyjąć swoją finalną formę:
class organizer: __właściciel = "" __bazaDanych = [] def __init__(self, właściciel): self.właściciel = właściciel def dodajNotatkę(self): priorytet = input("Priorytet:") tytuł = input("Tytuł:") treść = input("Treść:") nowaNotatka = notatka (priorytet, tytuł, treść) self.__bazaDanych.append(nowaNotatka) def dodajWizytówkę(self): priorytet = input("Priorytet:") imię = input("Imię:") nazwisko = input("Nazwisko:") telefon = input("Telefon:") nowaWizytówka = wizytówka(priorytet, imię, nazwisko, telefon) self.__bazaDanych.append(nowaWizytówka) def wyświetlNotatki(self): print("Lista notatek:") for i in self.__bazaDanych: if i.typ == 'notatka': print(i) def wyświetlWizytówki(self): print('Lista wizytów') for i in self.__bazaDanych: if i.typ == 'wizytówka': print(i)
Interakcja z użytkownikiem
Temat, który nie został przez nas jeszcze, zaadresowany, to interakcja programu z użytkownikiem i wykonywanie jego poleceń.
Do tego celu, możemy wykorzystać pętle 'while’, w której:
- Drukowana jest instrukcja obsługi, prosząc użytkownika o podanie informacji o żądanej akcji
- W czytywać wybór użytkownika
- Na tej podstawie wywoływać metody obiektu 'organizer’. Który to uczywiście musi być wcześniej utworzony.
Taka interakcja, może mieć następującą postać:
organizerAnalityka = organizer("Anality.edu.pl") while True: print("""Co chcesz zrobić?: 1- Dodać notatkę 2- Dodać wizytówkę 3- Wyświetlić notatki 4- Wyświetlić wizytówki 0- Zamknać organizer""") x = input() if x == '0': break if x == '1': organizerAnalityka.dodajNotatkę() if x == '2': organizerAnalityka.dodajWizytówkę() if x == '3': organizerAnalityka.wyświetlNotatki() if x == '4': organizerAnalityka.wyświetlWizytówki()
I w tym momencie, nasz program, jest skończony z punktu widzenia funkcjonalnego. Powyższe kody można wgrać do jednego pliku i go uruchomić. My jednak mamy polecenie, aby był zbudowany w duchu modułowości Pythona, tak wiec musimy go jeszcze na te moduły podzielić.
Tym samym, mogą powstać 3 pliki, tak jak poniżej:
run.py
from organizer import organizer organizerAnalityka = organizer("Anality.edu.pl") while True: print("""Co chcesz zrobić?: 1- Dodać notatkę 2- Dodać wizytówkę 3- Wyświetlić notatki 4- Wyświetlić wizytówki 0- Zamknać organizer""") x = input() if x == '0': break if x == '1': organizerAnalityka.dodajNotatkę() if x == '2': organizerAnalityka.dodajWizytówkę() if x == '3': organizerAnalityka.wyświetlNotatki() if x == '4': organizerAnalityka.wyświetlWizytówki()
organizer.py
from przedmioty import notatka, wizytówka class organizer: __właściciel = "" __bazaDanych = [] def __init__(self, właściciel): self.właściciel = właściciel def dodajNotatkę(self): priorytet = input("Priorytet:") tytuł = input("Tytuł:") treść = input("Treść:") nowaNotatka = notatka (priorytet, tytuł, treść) self.__bazaDanych.append(nowaNotatka) def dodajWizytówkę(self): priorytet = input("Priorytet:") imię = input("Imię:") nazwisko = input("Nazwisko:") telefon = input("Telefon:") nowaWizytówka = wizytówka(priorytet, imię, nazwisko, telefon) self.__bazaDanych.append(nowaWizytówka) def wyświetlNotatki(self): print("Lista notatek:") for i in self.__bazaDanych: if i.typ == 'notatka': print(i) def wyświetlWizytówki(self): print('Lista wizytów') for i in self.__bazaDanych: if i.typ == 'wizytówka': print(i)
przedmioty.py
from abc import ABC, abstractmethod class przedmiot(ABC): def __init__ (self, typ, priorytet): self.typ = typ self.priorytet = priorytet @abstractmethod def __str__(self): pass class notatka(przedmiot): def __init__(self, priorytet, tytuł, treść): super().__init__("notatka", priorytet) self.tytuł = tytuł self.treść = treść def __str__(self): info = self.typ + "Priorytet " + self.priorytet + "\n" info += self.tytuł + "\n" info += self.treść + "\n" return info class wizytówka(przedmiot): def __init__(self, priorytet, imię, nazwisko, telefon): super().__init__("wizytówka", priorytet) self.imię = imię self.nazwisko = nazwisko self.telefon = telefon def __str__(self): info = self.typ + "Priorytet " + self.priorytet + "\n" info += self.imię + " " + self.nazwisko + "\n" info += self.telefon + "\n" return info
a sam program, możemy uruchomić poleceniem
$ python3 run.py
Podsumowując. Po rozłożeniu na czynniki pierwsze, zadanie okazało się nie takie trudne. Dużej mieże jest to połączenie wszystkiego tego co do tej pory się nauczyliśmy. Oczywiście rozwiązanie jest jedynie przykładowym rozwiązaniem, a każdy z nas, mógł dojść samodzielnie do innego. Zanim przejdziemy dalej, zapraszamy do samodzielnego rozwiązania poniższych ćwiczeń.
Ćwiczenia. Tym razem, bez rozwiązania 🙂
Ćwiczenie 1. Należy dodać, do naszego programu, kolejny przedmiot. Mianowicie – kupon rabatowy
Ćwiczenie 2. Należy rozszerzyć funkcjonalność naszego organizera o możliwość skasowania wybranego przedmiotu.
Python, NIE tylko dla początkujących
- Wstęp do kursu
- Moduły i pakiety
- Programowanie obiektowe – wstęp
- Programowanie obiektowe – dziedziczenie
- Programowanie obiektowe – hermetyzacja
- Mini projekt – Organizer <– bieżąca lekcja
- Funkcje rekurencyjne w Python
- Pisanie skryptów w Python
- Mini projekt – tajny agent, generator haseł
- *args oraz **kwargs
- Dekoratory w Python
- Mini projekt – tajny agent – kontakty
- Odwzorowanie list
- Podsumowanie oraz dalsze kroki