Klasy i obiekty w Pythonie

Photo of author

By maciekx

Programowanie zorientowane obiektowo (OOP) to fundamentalny paradygmat w świecie programowania, a język Python oferuje solidne narzędzia do jego wykorzystania. W tym opracowaniu zgłębimy tajniki klas i obiektów w Pythonie, omawiając kluczowe koncepcje i prezentując je na praktycznych przykładach.

Wprowadzenie do paradygmatu obiektowego

Sednem programowania obiektowego jest tworzenie bytów, które odzwierciedlają obiekty rzeczywiste lub abstrakcyjne. Te byty łączą w sobie dane, znane jako atrybuty, oraz czynności, nazywane metodami. Rozważmy obiekt „kot”:

  • Atrybuty: rasa, wiek, imię, umaszczenie
  • Metody: miauczenie, drapanie, spanie

Klasy pełnią rolę szablonów, definiując strukturę i zachowanie obiektów. Można je traktować jak „projekty” dla tworzonych na ich podstawie obiektów. Przykładowo, klasa „Kot” określałaby cechy wspólne wszystkich kotów, a poszczególne obiekty typu „kot” byłyby konkretnymi egzemplarzami tej klasy.

Definiowanie klasy w Pythonie

W Pythonie klasy tworzymy za pomocą słowa kluczowego class. Nazwy klas powinny być pisane zgodnie z konwencją CamelCase (z dużej litery każdego słowa). Wewnątrz klasy definiujemy atrybuty (zmienne) i metody (funkcje).


class Kot:
    """
    Klasa modelująca kota.
    """

    def __init__(self, rasa, wiek, imie, umaszczenie):
        """
        Konstruktor obiektu.
        """
        self.rasa = rasa
        self.wiek = wiek
        self.imie = imie
        self.umaszczenie = umaszczenie

    def miau(self):
        """
        Metoda symulująca miauczenie.
        """
        print("Miau!")
  

Kreowanie obiektów (instancji)

Aby powołać do życia obiekt (instancję) klasy, używamy nazwy klasy, przekazując w nawiasach wartości dla atrybutów.


kot1 = Kot("Perski", 7, "Filemon", "biały")
kot2 = Kot("Dachowiec", 2, "Mruczek", "czarny")
  

W tym momencie mamy dwa obiekty, kot1 i kot2, które są reprezentacjami klasy Kot. Każdy z nich ma swoje własne, unikatowe wartości atrybutów.

Uzyskiwanie dostępu do atrybutów i wywoływanie metod

Dostęp do atrybutów obiektu uzyskujemy za pomocą operatora kropki (.)


print(kot1.rasa)  

Wyświetli "Perski"

print(kot2.imie)

Wyświetli "Mruczek"

Metody obiektu wywołujemy analogicznie, również używając operatora kropki.


kot1.miau()  

Wyświetli "Miau!"

kot2.miau()

Wyświetli "Miau!"

Mechanizm dziedziczenia

Dziedziczenie umożliwia tworzenie nowych klas, które przejmują cechy i funkcjonalności istniejących klas. Klasa dziedzicząca to klasa potomna, a ta, od której dziedziczy, to klasa macierzysta.


class Zwierze:
    """
    Bazowa klasa reprezentująca zwierzę.
    """

    def __init__(self, gatunek, wiek):
        self.gatunek = gatunek
        self.wiek = wiek

    def wydaj_dzwiek(self):
        print("Zwierzę wydaje dźwięk.")

class Kot(Zwierze):
    """
    Pochodna klasa reprezentująca kota.
    """

    def __init__(self, rasa, wiek, imie, umaszczenie):
        super().__init__("kot", wiek)
        self.rasa = rasa
        self.imie = imie
        self.umaszczenie = umaszczenie

    def miau(self):
        print("Miau!")

Utworzenie obiektu kota

kot = Kot("Perski", 7, "Filemon", "biały")

Wywołanie metod z klasy bazowej i pochodnej

kot.wydaj_dzwiek()

Wyświetli "Zwierzę wydaje dźwięk."

kot.miau()

Wyświetli "Miau!"

Właściwości (Properties)

Właściwości stanowią sposób na ukrycie szczegółów implementacji atrybutów i kontrolowanie dostępu do nich. Wykorzystujemy dekoratory @property i @<nazwa_właściwości>.setter do definicji właściwości.


class Album:
    def __init__(self, tytul, artysta):
        self.tytul = tytul
        self.artysta = artysta
        self._ilosc_utworow = 0

    @property
    def ilosc_utworow(self):
        return self._ilosc_utworow

    @ilosc_utworow.setter
    def ilosc_utworow(self, wartosc):
        if wartosc > 0:
            self._ilosc_utworow = wartosc
        else:
            print("Ilość utworów musi być dodatnia.")

album = Album("Thriller", "Michael Jackson")
print(album.ilosc_utworow)  

Wyświetli 0

album.ilosc_utworow = 9 print(album.ilosc_utworow)

Wyświetli 9

album.ilosc_utworow = -2

Wyświetli "Ilość utworów musi być dodatnia."

print(album.ilosc_utworow)

Wyświetli 9

Metody statyczne i klasowe

Metody statyczne nie są powiązane z konkretnym obiektem, lecz z klasą. Wywołujemy je, odwołując się do nazwy klasy.


class Matematyka:
    @staticmethod
    def pomnoz(x, y):
        return x * y

print(Matematyka.pomnoz(5, 3))  

Wyświetli 15

Metody klasowe są związane z klasą i mogą korzystać z atrybutów klasy. Wywołujemy je, odwołując się do nazwy klasy.


class Telefon:
    liczba_telefonow = 0

    def __init__(self, model):
        self.model = model
        Telefon.liczba_telefonow += 1

    @classmethod
    def wyswietl_liczbe_telefonow(cls):
        print(f"Zarejestrowano {cls.liczba_telefonow} telefonów.")

telefon1 = Telefon("Samsung Galaxy S23")
telefon2 = Telefon("iPhone 14")

Telefon.wyswietl_liczbe_telefonow()  

Wyświetli "Zarejestrowano 2 telefonów."

Enkapsulacja

Enkapsulacja to technika ukrywania szczegółów implementacji atrybutów i metod w celu ochrony przed nieautoryzowanym dostępem. W Pythonie osiągamy to poprzez konwencję nazewnictwa:

  • Atrybuty prywatne – zaczynają się od podwójnego podkreślenia (__)
  • Metody prywatne – analogicznie, również zaczynają się od podwójnego podkreślenia (__)

class Portfel:
    def __init__(self, srodki):
        self.__srodki = srodki

    def zasil(self, kwota):
        self.__srodki += kwota

    def obciaz(self, kwota):
        if self.__srodki >= kwota:
            self.__srodki -= kwota
        else:
            print("Niewystarczające środki.")

    def pokaz_srodki(self):
        print(f"Srodki: {self.__srodki}")

portfel = Portfel(500)
portfel.zasil(200)
portfel.obciaz(100)
portfel.pokaz_srodki()  

Wyświetli "Srodki: 600"

Próba bezpośredniego dostępu do atrybutu prywatnego

#print(portfel.__srodki)

Błąd: AttributeError: prywatny dostęp

Abstrakcja

Abstrakcja polega na tworzeniu uproszczonych modeli obiektów, skupiając się na kluczowych cechach. W Pythonie abstrakcję osiągamy za pomocą klas abstrakcyjnych i metod abstrakcyjnych. Klas abstrakcyjnych nie można bezpośrednio instancjonować, a metody abstrakcyjne muszą być zaimplementowane w klasach potomnych.


from abc import ABC, abstractmethod

class Figura(ABC):
    @abstractmethod
    def oblicz_pole(self):
        pass

class Kwadrat(Figura):
    def __init__(self, bok):
        self.bok = bok

    def oblicz_pole(self):
        return self.bok * self.bok

class Kolo(Figura):
    def __init__(self, promien):
        self.promien = promien

    def oblicz_pole(self):
        return 3.14 * self.promien * self.promien

Próba utworzenia obiektu klasy abstrakcyjnej

#figura = Figura() # Błąd: TypeError: Nie można utworzyć instancji abstrakcyjnej klasy Figura z abstrakcyjnymi metodami oblicz_pole kwadrat = Kwadrat(5) print(kwadrat.oblicz_pole())

Wyświetli 25

kolo = Kolo(3) print(kolo.oblicz_pole())

Wyświetli 28.26

Korzyści płynące z programowania obiektowego

Programowanie obiektowe niesie ze sobą liczne zalety:

  • Modułowość: Kod jest dzielony na moduły (klasy), co ułatwia zarządzanie i ponowne wykorzystanie.
  • Zwięzłość: Redukcja powtórzeń w kodzie, co zwiększa jego czytelność i łatwość utrzymania.
  • Elastyczność: Łatwość dodawania nowych funkcjonalności bez modyfikowania istniejącego kodu.
  • Abstrakcja: Ukrywanie skomplikowanych szczegółów implementacji, co upraszcza kod i poprawia jego czytelność.
  • Dziedziczenie: Ponowne wykorzystanie kodu i tworzenie hierarchii klas.
  • Polimorfizm: Wykonywanie różnych akcji w zależności od typu obiektu.

Podsumowanie

Klasy i obiekty są fundamentalnymi elementami programowania obiektowego w Pythonie. Zrozumienie tych koncepcji jest niezbędne do tworzenia uporządkowanego, modułowego i łatwego w utrzymaniu kodu. W połączeniu z dziedziczeniem, enkapsulacją i abstrakcją, programowanie obiektowe otwiera drogę do tworzenia bardziej złożonych i elastycznych aplikacji.

Najczęściej zadawane pytania (FAQ)

1. Czym jest self w Pythonie?
self to specjalny parametr, który jest przekazywany do każdej metody instancji klasy. Odnosi się on do bieżącego obiektu, umożliwiając dostęp do jego atrybutów i metod.

2. Jaka jest różnica między klasą a obiektem?
Klasa to szablon, który definiuje atrybuty i metody. Obiekt to konkretna instancja klasy, posiadająca unikatowe wartości atrybutów.

3. Co to jest konstruktor?
Konstruktor to specjalna metoda, wywoływana automatycznie podczas tworzenia obiektu. Zazwyczaj inicjalizuje atrybuty obiektu.

4. Jak działa dziedziczenie w Pythonie?
Klasa potomna dziedziczy atrybuty i metody po klasie macierzystej. Może też definiować własne atrybuty i metody.

5. Do czego służą właściwości (properties)?
Właściwości pozwalają na kontrolowanie dostępu do atrybutów, ukrywając szczegóły implementacji i zapewniając spójność danych.

6. Czym różnią się metody statyczne od metod klasowych?
Metody statyczne nie są powiązane z żadnym konkretnym obiektem i nie mają dostępu do atrybutów instancji. Metody klasowe są związane z klasą i mają dostęp do atrybutów klasy.

7. Jak enkapsulacja chroni dane?
Enkapsulacja ukrywa implementację atrybutów i metod, ograniczając do nich dostęp. Zapewnia to spójność danych i ochronę przed niepożądanymi zmianami.

8. Czy w Pythonie można używać wielodziedziczenia?
Tak, Python wspiera wielodziedziczenie. Klasa potomna może dziedziczyć cechy z wielu klas macierzystych.

9. Co to jest polimorfizm?
Polimorfizm to możliwość używania tego samego kodu do wykonywania różnych działań, w zależności od typu obiektu.

10. Jakie są popularne biblioteki Python, które wykorzystują programowanie obiektowe?
Wiele znanych bibliotek Pythona bazuje na OOP, przykładowo:
* Django: Framework webowy oparty na paradygmacie OOP.
* Flask: Lekki framework webowy.
* NumPy: Biblioteka do obliczeń numerycznych.
* Pandas: Biblioteka do analizy danych.
* Scikit-learn: Biblioteka do uczenia maszynowego.

Tagi: Python, programowanie obiektowe, klasy, obiekty, dziedziczenie, enkapsulacja, abstrakcja, metody, atrybuty, konstruktor, polimorfizm, properties, metody statyczne, metody klasowe, FAQ


newsblog.pl