Zanurkuj w Pythonie/Klasa opakowująca UserDict: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
mNie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1:
{{Podświetl|py}}
== Zgłębianie klasy <tt>UserDict</tt
Klasa <tt>FileInfo</tt> działa podobnie do słownika, o czym mogliśmy się już wcześniej przekonać. Aby ją lepiej zgłębić przyjrzyjmy się klasie <tt>UserDict</tt> w module <tt>UserDict</tt>, która jest przodkiem klasy <tt>FileInfo</tt>. Nie ma w niej nic specjalnego; jest to klasa napisana w Pythonie i przechowywana w pliku o rozszerzeniu <tt class="lang-none">.py</tt>, przypomina ona inne kody Pythona. Moduł ten jest przechowywany w katalogu <tt>lib</tt>, który z kolei znajduje się w miejsce, gdzie masz zainstalowanego Pythona.
{{Infobox|
W <tt>ActivePython IDE on Windows</tt> możesz szybko otwierać dowolny moduł znajdujący się w twojej ścieżce do bibliotek
'''Przykład 5.9. Definicja klasy <tt>UserDict</tt>'''
Linia 40 ⟶ 41:
# <tt>clear</tt> jest normalną metodą klasy; jest dostępna publicznie i może być wołana przez kogokolwiek w dowolnej chwili. Zauważ, że <tt>clear</tt>, jak wszystkie metody klas, ma <tt>self</tt> jako pierwszy argument. (Pamiętaj, że nie dodajesz <tt>self</tt> gdy wywołujesz metodę; Python robi to za Ciebie.) Zauważ podstawową cechę tej klasy pojemnikowej: przechowuje prawdziwy słownik (dane) jako atrybut danych (składową), definiuje wszystkie metody, które ma prawdziwy słownik i w każdej z tych metod zwraca wynik odpowiedniej metody słownika. (Gdybyś zapomniał, metoda <tt>clear</tt> słownika kasuje jego szystkie klucze i wartości.)
# metoda <tt>copy</tt> słownika zwraca nowy słownik, będący dokładną kopią oryginału (mający takie same pary klucz-wartość). Ale klasa <tt>UserDict</tt> nie może po prostu wywołać <tt>self.data.copy</tt>, ponieważ ta metoda zwraca słownik a to co chcemy tu zrobić, to zwrócenie nowej instancji klasy takiej, jak <tt>self</tt>.
# Używamy atrybutu <tt>class</tt>, żeby sprawdzić, czy <tt>self</tt> jest obiektem klasy <tt>UserDict</tt>; jeśli tak, jesteś w domu, bo wiesz jak zrobić kopię <tt>UserDict</tt>: stwórz nowy obiekt <tt>UserDict</tt> i przekaż mu słownik wyciągnięty z <tt>self.data</tt>. Wtedy możesz od razu zwrócić nowy obiekt <tt>UserDict</tt> nie wykonując nawet instrukcji
#
# Pozostałe metody są bezpośrednimi przekierowaniami wywołującymi wbudowane metody na <tt>self.data</tt>.
{{Infobox|
W wersjach 2.2 i wcześniejszych nie można było bezpośrenio tworzyć podklas wbudowanych typów jak napisy, listy czy słowniki. Aby to zrekompensować, Python dostarcza klasy opakowujące, które naśladują zachowanie wbudowanych typów danych. Są to: <tt>UserString</tt>, <tt>UserList</tt>, and <tt>UserDict</tt>. Wykorzystując kombinację normalnych i specjalnych metod, klasa <tt>UserDict</tt> doskonale imituje słownik. W Pythonie 2.2 i nowszym możemy dziedziczyć bezpośrednio z wbudowanych typów danych, jak np. <tt>dict</tt>, czyli słownik. Przykład tego możemy znaleść przykładach dostarczonych wraz z tą książką, w pliku <tt class="lang-none">fileinfo_fromdict.py</tt>.
}}
W Pythonie możemy dziedziczyć bezpośrednio wbudowane typy danych, co pokazano wponiższym przykładzie. Tutaj mamy trzy różnicy w porównaniu z wersją korzystającą z klasy <tt>UserDict</tt>.
'''Przykład 5.11. Dziedziczenie bezpośrednio z wbudowanej klasy <tt>dict</tt>'''
class FileInfo(dict): #(1)
"store file metadata"
def __init__(self, filename=None): #(2)
self["name"] = filename
# Pierwsza różnica polega na tym, że nie importujemy modułu <tt>UserDicr</tt>, ponieważ <tt>dict</tt> jest wbudowanym typem danych i jest ciągle dostępny. Druga polega na tym, że dziedziczymy bezpośrednio z klasy <tt>dict</tt>, zamiast z klasy <tt>UserDict.UserDict</tt>.
# Trzecia różnica jest subtelna, lecz też bardzo ważna. Ponieważ <tt>UserDict</tt> pracuje w sposób wewnętrzny, wymaga, aby manualnie wywołać metodę <tt>__init__</tt>, która w odpowiedni sposób zainicjuje swoją wewnętrzną strukturę danych. Z kolei <tt>dict</tt> nie działa w ten sposób. Nie jest to klasa opakowująca i nie wymaga wyraźnej inicjalizacji.
<noinclude>
|