Python - klasy

Witam!

Dopiero się uczę Pythona i napotkałem na problem ze zrozumieniem zasad działania klas.

Czy ktoś może mi wytłumaczyć - na jabłkach - jak one działają?

Z góry dziękuję!

Witaj,

za przykład dam akurat długopis, bo będzie łatwiej do wytłumaczenia.

Wiadomo że każdy długopis składa się z paru właściwości. Są to kolor, grubość, rodzaj długopisu, długość. Możemy mieć jeden piękny, czerwony długopis i drugi zwykły niebieski. Mimo, że się różnią, to jednak każdy z nich to nadal długopis. Czyli czerwony pisak, reprezentuje klasę długopis o określonych właściwościach: kolor czerwony, 0.5mm, żelowy, 12cm.

Czyli w Pythonie można by ją zapisać tak:

class CzerwonyPisak(dlugopis):

	def __init__ self.dlugopis

??

Klasy są charakterystyczne nie tylko dla Pythona,ale też C++,Javy i ogólnie innych języków obiektowych,klasa to opis obiektów z czego mają się składać,np. mamy ogólną klasę samochód,która składa się z koloru,pojemności silnika,rodzaju paliwa,ubezpieczenia,szybkości,są to zmienne dowolnego typu.

Gdy stworzysz obiekt będzie to już jakiś konkretny model,obiektem klasy samochód może być Maluch,Opel,Volkswagen.

Obiekt ma też funkcje,czyli to co można z nim robić,samochodem można jechać,postawić,zatrzymać,zwolnić,zatankować,itd.

Ogólnie obiekty to połączone: dane i operacje wykonywane na tych danych. A klasy opisują obiekty. Dobrze nadają się do modelowania świata rzeczywistego. Wracając do Twojego przykładu, lepszym kodem będzie:

#!/usr/bin/env python


class Dlugopis:

	def __init__ (self, kolor="czerwony"):

		self.kolor = kolor


	def __str__ (self):

		return "Dlugopis({0})".format(self.kolor)



if __name__ == ' __main__':

	d1 = Dlugopis()

	d2 = Dlugopis("niebieski")

	print d1

	print d2

W programowaniu dąży się do wyodrębnienia abstrakcji. Pomyśl, gdybyś chciał mieć długopisy różnych kolorów musiałbyś napisać wiele klas. Kolor może być jedną z danych przechowywanych przez klasę - i już wystarczy jedna (oczywiście lepiej gdy zamiast napisu jest to powiedzmy kod RGB, ale przykład ma być prosty). Długopis jest czymś mniej konkretnym niż CzerwonyDlugopis (teraz zauważyłem, że napisałeś Pisak, ale nie chce mi się zmieniać już napisanego posta, wybacz). Języki OO oferują wiele mechanizmów związanych z klasami, a ich cel to umożliwić pisać mniej, wydajniej, zwiększyć użycie już napisanego kodu itp.

Ale głupio tłumaczycie, z takiej teorii nic się nie zrozumie.

Klasa to jest typ danych. Można tworzyć reprezentantów danej klasy (obiekty, instancje, ogólnie nazewnictwo to problem bo jest sporo wersji). I na obiektach możesz wykonywać różne (akcje, metody, funkcje) a także ustalać im pewne (cechy, pola, właściwości). Czyli tworzysz klase np BazaDanych:

  • robisz sobie pola:

user, password, host

i metode która się łączy z bazą danych np

dbconnect().

To samo z siebie nie zadziała bo jest to jakby typ danych, pudełko. Musisz zrobić obiekt czyli np robisz obiekt “połączenie” i ustawiasz mu cechy jakie dałeś na klasę

polaczenie.host = ‘host’;

polaczenie.password = ‘haslo’, i tak dalej, ile właściwości w klasie stworzysz tyle mozesz sobie ustawić a potem możesz sie polaczyc metoda z klasy ktora wywolujesz na obiekcie

polaczenie.dbconnect();

i tak dalej i tak dalej, oczywiscie to nie wszystko bo sa jeszcze rozne mechanizmy programowania OOP. A tłumaczylem Ci jedynie ogolny zarys, w pythonie jest na pewno inna składnia wiec musisz tego szukać sam bo ja nie znam kompletnie tego języka.

Dzięki serdeczne wszystkim za pomoc w zrozumieniu tego :slight_smile:

@nr47 mógłbym Cię prosić o opis tego co się dzieje w tym kodzie, krok po kroku?

Wiem że jest to coś na wzór konstruktora - __init__ i self - z tymi dwoma mam problem…

(ostrzegam, że nie piszę w Pythonie na co dzień, więc mogę się co do czegoś mylić, ale zaglądałem w dokumentację i raczej można wierzyć temu co napisałem poniżej)

Tak, __init__ to jakby - używając nomenklatury z innych języków - konstruktor. Zasadniczo służy do inicjalizacji obiektu danej klasy jakimiś danymi. Bez definiowania __init__ obiekt byłby pusty po stworzeniu. Dlatego w __init__ przypisuję do pola “kolor” kolor przekazany do metody __init__ (akurat napisałem tak, że ten parametr ma domyślną wartość, ale jeśli czytasz już o klasach, to takie rzeczy z Pythona powinieneś znać).

Co do self natomiast…

Metody klasy jako pierwszy parametr dostają obiekt, na którym zostały wywołane. Dzięki temu z metod mamy dostęp do obiektu, na którym zostały wywołane i możemy np. odczytać lub zapisać do niego dane. Tak jak w przykładzie: w __init__ zapisuję daną do pola kolor, w metodzie __str__ odczytuję pole kolor.

Nazwa self to tylko konwencja, jak mówi dokumentacja

Czyli Ty piszesz powiedzmy obiekt.metoda(arg1, arg2) przy wywołaniu, ale argumenty jakie dostajesz do metody “metoda” to (obiekt, arg1, arg2) i powinieneś ją zadeklarować jako

def metoda(self, arg1, arg2).

Tego, że __str__ to konwersja do napisu nie muszę chyba tłumaczyć?

Mam nadzieję, że rozjaśniłem, a jeśli nie, to pisz co jest niejasne. Jeśli coś jest niejasne to napisz jakie jeszcze języki znasz, może dałoby się wytłumaczyć na bazie podobieństw/różnic.