Zanurkuj w Pythonie/Tworzenie instancji klasy
Tworzenie instancji klasy
[edytuj]Tworzenie instancji klas jest dosyć proste. W tym celu wywołujemy klasę tak jakby była funkcją, dodając odpowiednie argumenty, które są określone w metodzie __init__. Zwracaną wartością będzie zawsze nowo utworzony obiekt.
FileInfo
>>> import fileinfo
>>> f = fileinfo.FileInfo("/music/_singles/kairo.mp3") #(1)
>>> f.__class__ #(2)
<class 'fileinfo.FileInfo'>
>>> f.__doc__ #(3)
u'przechowuje metadane pliku'
>>> f #(4)
{'plik': '/music/_singles/kairo.mp3'}
- Utworzyliśmy instancję klasy
FileInfo(zdefiniowaną w modulefileinfo) i przypisaliśmy właśnie utworzony obiekt do zmiennejf. Skorzystaliśmy z parametru"/music/_singles/kairo.mp3", a który będzie odpowiadał argumentowifilenamew metodzie__init__klasyFileInfo. - Każda instancja pewnej klasy ma wbudowany atrybut
__class__, który jest klasą danego obiektu. Programiści Javy mogą być zaznajomieni z klasąClass, która posiada metody takie jakgetName, czy teżgetSuperclass, aby pobrać metadane o pewnym obiekcie. W Pythonie ten rodzaj metadadanych, jest dostępny bezpośrednio z obiektu wykorzystując atrybuty takie jak__class__,__name__, czy__bases__. - Możemy pobrać notkę dokumentacyjną w podobny sposób, jak to czyniliśmy w przypadku funkcji czy modułu. Wszystkie instancje klasy współdzielą tę samą notkę dokumentacyjną.
- Pamiętamy, że metoda
__init__przypisuje argumentfilenamedoself["plik"]? To dobrze, w tym miejscu mamy rezultat tej operacji. Argumenty podawane podczas tworzenia instancji pewnej klasy są wysłane do metody__init__(wyłączając pierwszy argument,self. Python zrobił to za nas).
W Pythonie, aby utworzyć instancję pewnej klasy, wywołujemy klasę tak, jakby to była zwykła funkcja zwracająca pewną wartość. Python nie posiada jakiegoś kluczowego słowa jakim jest np. operator new w Javie czy C++.
|
Odśmiecanie pamięci
[edytuj]Jeśli tworzenie nowej instancji jest proste, to jej usuwanie jest jeszcze prostsze. W ogólności nie musimy wyraźnie zwalniać instancji klasy, ponieważ Python robi to automatycznie, gdy wychodzi one poza swój zasięg. W Pythonie rzadko występują wycieki pamięci.
>>> def leakmem():
... f = fileinfo.FileInfo('/music/_singles/kairo.mp3') #(1)
...
>>> for i in range(100):
... leakmem() #(2)
- Za każdym razem, gdy funkcja
leakmemjest wywoływana, zostaje utworzona instancja klasyFileInfo, a ta zostaje przypisana do zmiennejf, która jest lokalną zmienną wewnątrz funkcji. Funkcja ta kończy się bez jakiegokolwiek wyraźnego zwolnienia pamięci zajmowanej przez zmiennąf, a więc spodziewalibyśmy się wycieku pamięci, lecz tak nie będzie. Kiedy funkcja się kończy, lokalna zmiennafwychodzi poza swój zasięg. W tym miejscu nie ma więcej żadnych referencji do nowej instancjiFileInfo, ponieważ nigdzie nie przypisywaliśmy jej do czegoś innego niżf, tak więc Python zniszczy instancję za nas. - Niezależnie od tego, jak wiele razy wywołamy funkcję
leakmem, nigdy nie nastąpi wyciek pamięci, ponieważ za każdym razem kiedy to zrobimy, Python będzie niszczył nowo utworzony obiekt przed wyjściem z funkcjileakmem.
Technicznym terminem tego sposobu odśmiecania pamięci jest "zliczanie odwołań" (zobacz w Wikipedii). Python przechowuje listę referencji do każdej utworzonej instancji. W powyższym przykładzie, mamy tylko jedną referencję do instancji FileInfo -- zmienną f. Kiedy funkcja się kończy, zmienna f wychodzi poza zasięg, więc licznik odwołań zmniejsza się do 0 i Python zniszczy tę instancję automatycznie.
W poprzednich wersjach Pythona występowały sytuacje, gdy zliczanie odwołań zawodziło i Python nie mógł wyczyścić po nas pamięci. Jeśli tworzyliśmy dwie instancje, które odwoływały się do siebie nawzajem (np. instancja listy dwukierunkowej[1], w których każdy węzeł wskazuje na poprzedni i następny znajdujący się w liście), żadna instancja nie była niszczona automatycznie, ponieważ Python uważał (poprawnie), że ciągle mamy referencję do każdej instancji. Od Pythona 2.0 mamy dodatkowy sposób odśmiecania pamięci, nazywany po ang. mark-and-sweep (oznacz i zamiataj, zobacz w Wikipedii), dzięki któremu Python w sprytny sposób wykrywa różne wirtualne blokady i poprawnie czyści cykliczne odwołania.
Podsumowując, w języku tym można po prostu zapomnieć o zarządzaniu pamięcią i pozostawić tę sprawę Pythonowi.
Materiały dodatkowe
[edytuj]- Python Library Reference omawia wbudowane atrybuty podobne do
__class__ - Python Library Reference dokumentuje moduł
gc, który daje niskopoziomową kontrolę nad odśmiecaniem pamięci
Przypisy
[edytuj]- ↑ ang. double linked list