Zanurkuj w Pythonie/Klasa opakowująca UserDict: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Piotr (dyskusja | edycje)
Piotr (dyskusja | edycje)
mNie podano opisu zmian
Linia 1:
{{Podświetl|py}}
== ZgłębianieKlasa klasyopakowująca <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.
Linia 20:
# metoda <tt>update</tt> jest duplikatorem słownika: kopiuje wszystkie klucze i wartości z jednego słownika do drugiego. Ta metoda nie czyści słownika docelowego; jeśli były tam już jakieś klucze, te, które są w słowniku źródłowym zostaną nadpisane ale pozostałe się nie zmienią. Myśl o <tt>update</tt> jak o funkcji łączenia, nie kopiowania.
# tej składni mogłeś wcześniej nie widzieć (nie używałem jej w przykładach z tej książki). Jest to instrukcja <tt>if</tt> ale zamiast wciętego bloku zaczynającego się w następnej linii jest tu pojedyncza instrukcja w tej samej linii, za dwukropkiem. Jest to całkowicie poprawna składnia, będąca tylko skrótem, którego możesz używać, jeśli masz tylko jedną instrukcję w bloku (tak jak pojedyncza instrukcja bez klamer w C++). Możesz użyć tej składni albo wciętego kodu w następnych liniach, ale nie możesz użyć obu składni w tym samym bloku kodu.
 
{{Infobox|
Java i Powerbuilder mogą przeciążać funkcje mające różne listy argumentów, na przykład klasa może mieć kilka metod z taką samą nazwą ale z różną liczbą argumentów lub z argumentami różnych typów. Inne języki (na przykład PL/SQL) obsługują nawet przeciążanie funkcji różniących się nazwą argumentu. Na przykład jedna klasa może mieć kilka metod z tą samą nazwą, tą samą liczbą argumentów tych samych typów ale inaczej nazwanych. Python nie ma żadnej z tych możliwości, nie ma w ogóle przeciążania funkcji. Metody są jednoznacznie definiowane przez ich nazwy i w danej klasie może być tylko jedna metoda o danej nazwie. Jeśli więc metoda potomna ma klasę <tt>__init__</tt>, to zawsze zasłoni ona metodę <tt>__init__</tt> klasy-przodka nawet, jeśli klasa pochodna definiuje ją z innymi argumentami. Ta uwaga stosuje się do wszystkich metod.}}
 
{{Infobox|
Guido, pierwszy twórca Pythona, tak wyjaśnia zasłanianie funkcji: "Klasy pochodne mogą zasłonić metody klas bazowych. Ponieważ metody nie mają żadnych specjalnych przywilejów wołając inne metody tego samego obiektu, może okazać się, że metoda klasy bazowej wołająca inną metodę zdefiniowaną w tej samej klasie bazowej woła właściwie metodę klasy pochodnej która ją zasłania. (Dla programistów C++: wszystkie metody w Pythonie zachowują się jakby były wirtualne.)" Jeśli dla Ciebie nie ma to sensu (mnie osobiście strasznie wkurza), możesz to zignorować. Uważałem, że należy o tym wspomnieć.}}
 
{{Uwaga|
Zawsze przypisuj wartość początkową wszystkim zmiennym obiektu w jego metodzie <tt>__init</tt>. Oszczędzi to godzin debugowania w poszukiwaniu wyjątków <tt>AtributeError</tt> powodowanych przez odwołania do niezainicjalizowanych (czyli nieistniejących) atrybutów.}}
Linia 39 ⟶ 42:
def values(self): return self.data.values()
 
# <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 klasyopakowującej pojemnikowejklasy: przechowuje prawdziwy słownik (dane<tt>data</tt>) jako atrybut danych (składową),i definiuje wszystkie metody, które ma prawdziwy słownik, ia w każdej z tych metod zwraca wynik identyczny do 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 <tt>import</tt> z następnej linii.
Linia 46 ⟶ 49:
 
{{Infobox|
1=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>.
}}