Programowanie obiektowe - własne funkcje i obiekty
title: Zajęcia 10 - funkcje, klasy author: Przemek Jeske, Robisz.to
Funkcje
Do tej pory korzystaliśmy z funkcji dostarczonych nam przez Pythona (np . print
), lub "wgranych" z biblioteki / modułu.
Pisząc własne programy już na tym etapie zetknęliśmy się z sytuacją gdy robiliśmy podobną rzecz wiele razy - zmieniały się np. tylko dane wejściowe np. modyfikowaliśmy jakiś adres w książce adresowej, gdzie zmieniało się tylko, który adres był modyfikowany.
Możemy taką funkcjonalność ;) zebrać w całość i udostępnić jako własną funkcję.
Własną funkcję deklarujemy używając słowa def
.
np.
def kwadrat(x:int) -> int:
wynik = x * x
return wynik
Zwróćcie uwagę na słowo return
- wykorzystujemy je jeśli chcemy, żeby nasza funkcja poza wykonaniem jakiejś operacji zwróciła nam jakąś wartość (którą np. możemy przypisać do zmiennej). Bardzo dużo funkcji korzysta z tej opcji - np. funkcja sum
zwraca nam sumę dwóch liczb, funkcja max
zwraca nam największą wartość przechowywaną chociażby na liście itd.
Nie jest to jednak reguła - np. funkcja print
wyświetla nam daną zawartość na ekranie, ale nie zwraca żadnej wartości.
Powyższy przykład zawiera nieco nieobowiązkowych rzeczy:
- informację o oczekiwanym typie danych parametru wykorzystywanego w funkcji (
x:int
) - informację o zwracanym typie danych (
-> int
)
Dodawanie tych informacji jest dobrą praktyką - ułatwia nam (i innym użytkownikom tego kodu) korzystanie z programu.
Ponadto dzięki nim narzędzia jakich używamy do pisania będą w stanie podpowiadać nam w przypadku popełnienia błędu związanego z użyciem nieprawidłowego typu.
Tak skonstruowana funkcje wykorzystujemy identycznie jak te wbudowane np.
def kwadrat(x:int) -> int:
wynik = x * x
return wynik
liczba = kwadrat(2)
print(liczba)
Powyższa kod wyświetli nam 4
gdyż jest to 2
podniesione do kwadratu (a właśnie to robi ta funkcja kwadrat).
Klasy
Zazwyczaj chcemy żeby w naszym kodzie było możliwie mało powtórzeń, całość była jak najbardziej czytelna, a osoby korzystające z naszego programu miały jasne wytyczne czego nasz kod oczekuje.
Jednym z narzędzi w drodze do tego celu są klasy, będące fundamentem podejścia nazywanego programowaniem obiektowym.
Korzystając z tej metody staramy się modelować nasz kod w sposób nieco przypominający to jak zbieramy informacje o otaczającym nas świecie. Np. grupujemy gatunki w podobne kategorie. Pies domowy należy do rodziny psowatych, które z kolei należą do rzędu ssaków drapieżnych.
Mimo tego, że psy różnią się od siebie (ciężko pomylić jamnika z dobermanem) to mają one pewne cechy wspólne, które umożliwiają nam przypisanie ich do tego typu (gatunku).
Podobnie modelując aplikację staramy się znaleźć jakieś elementy wspólne obiektów, które tworzymy i na tej podstawie stworzyć typ grupujący je - służy on jako swego rodzaju szablon do stworzenia nowych obiektów.
Oprócz cech charakterystycznych (atrybutów) klasa zawiera też metody - czyli rzeczy, które dany obiekt może robić.
Jako przykład posłużmy się postacią do gry komputerowej rpg. Każda z nich będzie miała jakieś punkty życia, punkty magii, profesję itd. Żeby nie wymyślać tej struktury za każdym razem możemy zdefiniować odpowiednią klasę:
class PostacGracza:
def __init__(self, imie, profesja):
self.imie = imie
self.profesja = profesja
self.hp = 100
self.mana = 100
gracz1 = PostacGracza("Fizban", "mag")
gracz2 = PostacGracza("Taz", "łotrzyk")
Obie stworzone postaci (gracz1 i gracz2) zostały zrobione na podstawie tego samego szablonu (klasy PostacGracza
), ale nie są identyczne - różnią się imieniem i profesją. Co więcej pozostałe ich atrybuty (hp i mana) mimo, że na start mają tę samą wartość są od siebie całkowicie niezależne (są to zupełnie osobne wartości). Czyli np. jeśli w trakcie gry Fizban otrzyma 30 obrażeń to będzie miał on 70 hp, podczas gdy Taz nadal będzie miał 100.
Tworzenie klasy
Metoda __init__
- to sekcja, która jest uruchamiana podczas tworzenia naszego obiektu na podstawie szablonu (klasy). Umożliwia przypisanie obiektowi jego indywidualnych cech (w powyższym przykładzie będzie to hp, mana, imie, profesja), lub wykonanie jakiś czynności na starcie. Czyli mamy "szkielet" i w tym momencie wypełniamy go "mięsem".
- sama definicja tej funkcji przestrzega wcześniejszych zasad np. warto opisywać typy jakie mają być przekazane
- bardzo istotne jest tutaj słowo
self
. Wskazuje one, że przypisujemy cechy do tego konkretnego obiektu, nie do całej klasy.
Odnośniki
„3.12.5 Documentation”. Dostęp 18 sierpień 2024. https://docs.python.org/3/.