Želite li da započnete s objektno orijentisanim dizajnom u Pythonu? Napravite prve korake već danas tako što ćete se upoznati sa `__init__` metodom u Pythonu.
U ovom uputstvu, istražićemo osnove klasa i objekata u Pythonu, a zatim ćemo detaljno proučiti metodu `__init__`.
Nakon ovog tutorijala, moći ćete odgovoriti na sledeća pitanja:
- Šta su to varijable instance ili atributi instance?
- Kako metoda `__init__` pomaže u inicijalizaciji atributa instance?
- Kako možemo podesiti podrazumevane vrednosti za atribute?
- Kako možemo koristiti metode klase kao konstruktore za kreiranje objekata?
Krenimo!
Python Klase i Objekti
Klase su temeljne za objektno orijentisano programiranje u Pythonu. Možemo kreirati klasu i unutar nje definisati atribute i metode – kako bismo povezali podatke i funkcije koje rade s tim podacima.
Nakon što napravimo klasu, možemo je koristiti kao šablon za kreiranje objekata (instanci).
👩🏫 Primer! Hajde da kreiramo klasu `Zaposleni` gde će svaki objekat ove klase imati sledeće atribute:
- `puno_ime`: puno ime zaposlenog u formatu ime prezime
- `emp_id`: ID zaposlenog
- `odeljenje`: odeljenje kojem pripada
- `iskustvo`: broj godina iskustva
Šta to znači? 🤔
Svaki pojedinačni zaposleni biće instanca ili objekat klase `Zaposleni`. Svaki objekat imaće sopstvenu vrednost za `puno_ime`, `emp_id`, `odeljenje` i `iskustvo`.
Ovi atributi se takođe nazivaju varijable instance, a termine atributi i varijable instance koristićemo naizmenično.
Do dodavanja atributa doći ćemo malo kasnije. Za sada, kreiramo klasu `Zaposleni` ovako:
class Employee: pass
Korišćenje `pass` (kao čuvara mesta) pomaže nam da izbegnemo greške kada pokrenemo skriptu.
Iako trenutna verzija klase `Zaposleni` nije od velike koristi, ona je ipak validna klasa. Zato možemo kreirati objekte klase `Zaposleni`:
employee_1 = Employee() print(employee_1) #Output: <__main__.Employee object at 0x00FEE7F0>
Takođe možemo dodati atribute i inicijalizovati ih vrednostima kao što je prikazano:
employee_1.full_name="Amy Bell" employee_1.department="HR"
Ali ovaj pristup dodavanju atributa instance je neefikasan i podložan greškama. Takođe, ne omogućava korišćenje klase kao šablona za kreiranje objekata. Tu metoda `__init__` stupa na scenu.
Razumevanje Uloge `__init__` Metode u Python Klasi
Trebalo bi da budemo u mogućnosti da inicijalizujemo varijable instance prilikom kreiranja objekta, a metoda `__init__` nam u tome pomaže. Metoda `__init__` se poziva svaki put kada se kreira novi objekat klase radi inicijalizacije vrednosti varijabli instance.
Ako ste programirali u jeziku kao što je C++, videćete da metoda `__init__` funkcioniše slično kao konstruktori.
Definisanje Metoda `__init__`
Dodajmo metodu `__init__` u klasu `Zaposleni`:
class Employee: def __init__(self, full_name,emp_id,department,experience): self.full_name = full_name self.emp_id = emp_id self.department = department self.experience = experience
Parametar `self` odnosi se na instancu klase, a `self.attribute` inicijalizuje atribut instance na vrednost sa desne strane.
Sada možemo kreirati objekte kao što je ovaj:
employee_2 = Employee('Bella Joy','M007','Marketing',3) print(employee_2) # Output: <__main__.Employee object at 0x017F88B0>
Kada ispišemo objekte zaposlenih, ne dobijamo nikakve korisne informacije osim klase kojoj pripadaju. Dodajmo metodu `__repr__` koja definiše niz za predstavljanje klase:
def __repr__(self): return f"{self.full_name},{self.emp_id} iz {self.department} sa {self.experience} godina iskustva."
Dodavanjem `__repr__` u klasu `Zaposleni`, imamo:
class Employee: def __init__(self, full_name,emp_id,department,experience): self.full_name = full_name self.emp_id = emp_id self.department = department self.experience = experience def __repr__(self): return f"{self.full_name},{self.emp_id} iz {self.department} sa {self.experience} godina iskustva."
Sada objekti zaposlenih imaju koristan niz za predstavljanje:
print(employee_2) # Output: Bella Joy,M007 iz Marketinga sa 3 godina iskustva.
Nekoliko Konvencija
Pre nego što nastavimo dalje, evo nekoliko napomena:
- Koristili smo `self` kao prvi parametar u metodi `__init__` za upućivanje na samu instancu klase i koristili `self.ime_atributa` za inicijalizaciju različitih atributa. Korišćenje `self` je preferirana konvencija (iako možete koristiti bilo koje drugo ime).
- Kada definišemo metodu `__init__`, imena parametara u `__init__` definicijama podešavamo tako da odgovaraju imenima atributa. Ovo poboljšava čitljivost.
Kako Dodati Podrazumevane Vrednosti za Atribute
U primeru koji smo do sada kodirali, svi atributi su obavezni. To znači da je kreiranje objekta uspešno samo ako konstruktoru prosledimo vrednosti za sva polja.
Pokušajte da instancirate objekat klase `Zaposleni` bez prosleđivanja vrednosti za atribut `iskustvo`:
employee_3 = Employee('Jake Lee','E001','Engineering')
Dobićete sledeću grešku:
Traceback (most recent call last): File "main.py", line 22, in <module> employee_3 = Employee('Jake Lee','E001','Engineering') TypeError: __init__() missing 1 required positional argument: 'experience'
Ali ako želite da određene atribute učinite opcionalnim, to možete uraditi tako što ćete obezbediti podrazumevane vrednosti za te atribute kada definišete metodu `__init__`.
Ovde dajemo podrazumevanu vrednost 0 za atribut `iskustvo`:
class Employee: def __init__(self, full_name,emp_id,department,experience=0): self.full_name = full_name self.emp_id = emp_id self.department = department self.experience = experience def __repr__(self): return f"{self.full_name},{self.emp_id} iz {self.department} sa {self.experience} godina iskustva."
Objekat `employee_3` je kreiran bez vrednosti za atribut `iskustvo`; podrazumevana vrednost 0 se koristi za iskustvo.
employee_3 = Employee('Jake Lee','E001','Engineering') print(employee_3.experience) # Output: 0
Alternativni Konstruktori Klasa Koji Koriste Metode Klase
Do sada smo videli samo kako da definišemo metodu `__init__` i postavimo podrazumevane vrednosti za atribute kada je to potrebno. Takođe znamo da treba da prosledimo vrednosti za tražene atribute u konstruktoru.
Ponekad, međutim, vrednosti za ove varijable instance (ili atribute) mogu biti dostupne u drugoj strukturi podataka, kao što je tuple, rečnik ili JSON string.
Pa šta da radimo?
Uzmimo primer. Pretpostavimo da imamo vrednosti varijable instance u Python rečniku:
dict_fanny = {'name':'Fanny Walker','id':'H203','dept':'HR','exp':2}
Možemo da pristupimo rečniku i dobijemo sve atribute ovako:
name = dict_fanny['name'] id = dict_fanny['id'] dept = dict_fanny['dept'] exp = dict_fanny['exp']
Nakon toga možete kreirati objekat tako što ćete proslediti ove vrednosti u konstruktor klase:
employee_4 = Employee(name, id, dept, exp) print(employee_4) # Output: Fanny Walker,H203 iz HR-a sa 2 godina iskustva.
Zapamtite: ovo morate da uradite za svaki novi objekat koji kreirate. Ovaj pristup je neefikasan i definitivno možemo bolje. Ali kako?
U Pythonu možemo koristiti metode klase kao konstruktore za kreiranje objekata klase. Za kreiranje metode klase koristimo dekorator `@classmethod`.
Hajde da definišemo metodu koja analizira rečnik, dobija vrednosti varijable instance i koristi ih za kreiranje objekata `Zaposleni`.
@classmethod def from_dict(cls,data_dict): full_name = data_dict['name'] emp_id = data_dict['id'] department = data_dict['dept'] experience = data_dict['exp'] return cls(full_name, emp_id, department, experience)
Kada treba da kreiramo objekte koristeći podatke iz rečnika, možemo koristiti metodu klase `from_dict()`.
💡 Obratite pažnju na upotrebu `cls` u metodi klase umesto `self`. Baš kao što koristimo `self` za upućivanje na instancu, `cls` se koristi za upućivanje na klasu. Takođe, metode klase su vezane za klasu, a ne za objekte.
Dakle, kada pozovemo metodu klase `from_dict()` za kreiranje objekata, pozivamo je u klasi `Zaposleni`:
emp_dict = {'name':'Tia Bell','id':'S270','dept':'Sales','exp':3} employee_5 = Employee.from_dict(emp_dict) print(employee_5) # Output: Tia Bell,S270 iz Prodaje sa 3 godina iskustva.
Sada, ako imamo rečnik za svakog od n zaposlenih, možemo koristiti metodu klase `from_dict()` kao konstruktor za instanciranje objekata – bez potrebe da preuzimamo vrednosti trenutne varijable iz rečnika.
📝Napomena o klasnim varijablama
Ovde smo definisali metodu klase koja je vezana za klasu, a ne za pojedinačne instance. Slično metodama klase, možemo imati i varijable klase.
Kao i metode klase, varijable klase su vezane za klasu, a ne za instancu. Kada atribut ima fiksnu vrednost za sve instance klase, možemo razmotriti da ih definišemo kao varijable klase.
Često Postavljana Pitanja
1. Zašto vam je potrebna metoda `__init__` u Pythonu?
Metoda `__init__` u definiciji klase omogućava nam da inicijalizujemo atribute ili varijable instance svih instanci klase. Metoda `__init__` se poziva svaki put kada se kreira nova instanca klase.
2. Možete li imati više metoda `__init__` u Python klasi?
Cilj postojanja više metoda `__init__` u Python klasi je da se obezbedi više konstruktora koji instanciraju objekte. Ali ne možete definisati više metoda `__init__`. Ako definišete više metoda `__init__`, druga i najnovija implementacija će zameniti prvu. Međutim, možete koristiti dekorator `@classmethod` da definišete metode klase koje se mogu koristiti kao konstruktori za instanciranje objekata.
3. Šta se dešava ako ne definišete metodu `__init__` u klasi?
Ako ne definišete metodu `__init__`, i dalje možete instancirati objekte. Međutim, moraćete ručno da dodate varijable instance i dodelite vrednosti svakoj od njih. Nećete moći da prosledite vrednosti za varijable instance u konstruktoru. Ovo ne samo da je sklono greškama, već i poništava svrhu postojanja klase kao nacrta iz kojeg možemo instancirati objekte.
4. Možete li imati podrazumevane vrednosti za argumente u metodi `__init__`?
Da, moguće je obezbediti podrazumevane vrednosti za jedan ili više atributa prilikom definisanja metode `__init__`. Pružanje podrazumevanih vrednosti pomaže da ti atributi budu opcionalni u konstruktoru. Atributi uzimaju podrazumevane vrednosti kada ne prosledimo vrednosti za te atribute u konstruktoru.
5. Možete li da izmenite atribute van metode `__init__`?
Da, uvek možete ažurirati vrednost atributa van metode `__init__`. Takođe možete dinamički dodati nove atribute instanci nakon što ste kreirali određenu instancu.
Zaključak
U ovom vodiču smo naučili kako da koristimo metodu `__init__` za inicijalizaciju vrednosti varijabli instance. Iako je ovo jednostavno, može biti ponavljajuće – posebno kada imate mnogo atributa.
Ako ste zainteresovani, možete istražiti modul klasa podataka. U Pythonu 3.7 i novijim verzijama, možete koristiti ugrađeni modul klasa podataka za kreiranje klasa podataka koje čuvaju podatke. Pored podrazumevanih implementacija `__init__` i drugih često korišćenih metoda, one dolaze sa mnogo sjajnih funkcija za nagoveštaje tipa, složene podrazumevane vrednosti i optimizaciju.
Zatim saznajte više o tome da li je `__name__` == `__main__` u Pythonu.