Metody specjalne czyli Metody magiczne

Metody specjalne (nazywane również „magic methods” lub „dunder methods” – skrót od „double underscore”) to specjalne nazwy metod w języku Python, które pozwalają na dostosowanie zachowania klas do różnych operacji lub wywołań. Te metody są wywoływane automatycznie przez interpreter Python w określonych sytuacjach. Oto kilka przykładów i wyjaśnień:

  1. __init__(self, ...): To jest konstruktor klasy, wywoływany podczas tworzenia nowej instancji obiektu. Pozwala na inicjalizację atrybutów obiektu.
  2. __str__(self): Ta metoda jest wywoływana przez funkcję str(), która konwertuje obiekt na czytelny dla człowieka łańcuch znaków. Powinna zwrócić reprezentację tekstową obiektu.
  3. __repr__(self): Ta metoda jest wywoływana przez funkcję repr(), która konwertuje obiekt na reprezentację tekstową, która powinna być jak najbardziej precyzyjna i mogłaby być użyta do rekreacji obiektu.
  4. __len__(self): Ta metoda jest wywoływana przez funkcję len(), która zwraca długość obiektu. Dla przykładu, może być używana dla klas reprezentujących kolekcje, aby zwrócić ilość elementów.
  5. __add__(self, other): Ta metoda umożliwia zdefiniowanie, co powinno się stać, gdy operator dodawania + jest użyty między dwoma obiektami.
  6. __eq__(self, other): Ta metoda pozwala na zdefiniowanie, jakie warunki muszą być spełnione, aby dwa obiekty były uważane za równe. Jest wywoływana przez operator ==.
  7. __lt__(self, other): Ta metoda pozwala na zdefiniowanie, co oznacza, że dany obiekt jest mniejszy od innego. Jest wywoływana przez operator <.
  8. __getitem__(self, key): Pozwala na zdefiniowanie, jakie zachowanie powinno być dla indeksowania obiektu, jak w przypadku list czy słowników.
  9. __setitem__(self, key, value): Pozwala na zdefiniowanie, jakie zachowanie powinno być dla przypisania wartości do indeksu obiektu.
  10. __del__(self): Ta metoda jest wywoływana podczas usuwania obiektu. Można w niej umieścić kod, który ma być wykonany przed usunięciem obiektu z pamięci.

Istnieje wiele innych metod specjalnych, które pozwalają na bardziej zaawansowane dostosowanie zachowania klas do różnych sytuacji. Dzięki tym metodom, możesz bardziej precyzyjnie kontrolować, jak obiekty danej klasy zachowują się w różnych kontekstach.

Przykłady:

__init__(self, ...): Konstruktor klasy.

class Osoba:
    def __init__(self, imie, wiek):
        self.imie = imie
        self.wiek = wiek

osoba = Osoba("Anna", 30)
print(osoba.imie, osoba.wiek)

__str__(self): Metoda reprezentująca obiekt jako łańcuch znaków.

class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Punkt({self.x}, {self.y})"

punkt = Punkt(5, 10)
print(punkt)

__repr__(self): Metoda reprezentująca obiekt w sposób rekreowalny.

class Ksiazka:
    def __init__(self, tytul, autor):
        self.tytul = tytul
        self.autor = autor

    def __repr__(self):
        return f"Ksiazka('{self.tytul}', '{self.autor}')"

ksiazka = Ksiazka("Harry Potter", "J.K. Rowling")
print(repr(ksiazka))

__len__(self): Metoda zwracająca długość obiektu.

class ListaLiczb:
    def __init__(self, liczby):
        self.liczby = liczby

    def __len__(self):
        return len(self.liczby)

lista = ListaLiczb([1, 2, 3, 4, 5])
print(len(lista))

__add__(self, other): Metoda definiująca zachowanie operatora dodawania +.

class Liczba:
    def __init__(self, wartość):
        self.wartość = wartość

    def __add__(self, other):
        return Liczba(self.wartość + other.wartość)

a = Liczba(5)
b = Liczba(10)
c = a + b
print(c.wartość)

__eq__(self, other): Metoda definiująca zachowanie operatora równości ==.

class Osoba:
    def __init__(self, imie):
        self.imie = imie

    def __eq__(self, other):
        return self.imie == other.imie

osoba1 = Osoba("Anna")
osoba2 = Osoba("Anna")
print(osoba1 == osoba2)

__lt__(self, other): Metoda definiująca zachowanie operatora mniejszości <.

class Liczba:
    def __init__(self, wartość):
        self.wartość = wartość

    def __lt__(self, other):
        return self.wartość < other.wartość

a = Liczba(5)
b = Liczba(10)
print(a < b)

__getitem__(self, key): Metoda umożliwiająca indeksowanie obiektu.

class ListaKwadratow:
    def __init__(self, liczby):
        self.liczby = liczby

    def __getitem__(self, index):
        return self.liczby[index] ** 2

lista = ListaKwadratow([1, 2, 3, 4, 5])
print(lista[2])

__setitem__(self, key, value): Metoda umożliwiająca przypisanie wartości do indeksu obiektu.

class ListaKwadratow:
    def __init__(self, liczby):
        self.liczby = liczby

    def __setitem__(self, index, value):
        self.liczby[index] = value

lista = ListaKwadratow([1, 2, 3, 4, 5])
lista[2] = 9
print(lista.liczby)

__del__(self): Metoda wywoływana przy usuwaniu obiektu.

class Ksiazka:
    def __init__(self, tytul):
        self.tytul = tytul

    def __del__(self):
        print(f"Książka '{self.tytul}' zostaje usunięta")

ksiazka = Ksiazka("Władca Pierścieni")
del ksiazka