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

Usunięta treść Dodana treść
Piotr (dyskusja | edycje)
mNie podano opisu zmian
Piotr (dyskusja | edycje)
Nie podano opisu zmian
Linia 1:
{{Podświetl|py}}
== Zgłębianie klasy <tt>UserDict</tt> <!--A Wrapper Class --> ==
 
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 <!--your library path--> wybierając ''File->Locate... (Ctrl-L)''.}}
 
'''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 <font color=blue><tt>'''import'''</tt></font> z następnej linii.
# IfJeśli <tt>self.__class__</tt> isnie notjest <tt>UserDict</tt>-em, thento <tt>self</tt> mustmusi bebyć somejakąś subclass ofpodklasą <tt>UserDict</tt>-a (likejak być maybemoże <tt>FileInfo</tt>), <!-- in which case life gets trickier -->. <tt>UserDict</tt> doesn'tnie knowwie, howjak toutworzyć makedokładną ankopię exactjednego copyze ofswoich onepotomków. ofW itstym descendants;celu theremożemy could,np. forznając instance,atrybuty bezdefiniowane otherw data attributes defined in the subclasspodklasie, sowykonać youna wouldnich neediterację tokopiując iteratekażdy throughz themtych andatrybutów. makeNa sureszczęście toistnieje copy all of them. Luckilymoduł, Pythonktóry comeswykonuje with a moduledokładnie to do exactly thissamo, andnazywa it'ssię calledon <tt>copy</tt>. INie won'tbędziemy gosię intotutaj thewdawać detailsw hereszczegóły (thoughchoć it'sjest ato wickedniezły (cool) modulemoduł, ifjeśli you'rewgłębisz eversię inclined to dive into it onw yourniego ownsamemu). SufficeWystarczy itwiedzieć, toże say<tt>copy</tt> thatpotrafi copykopiować candowolne copyobiekty, arbitrarya Pythontu objectswidzimy, and that's howjak you'remożemy usingz itniego hereskorzystać.
# Pozostałe metody są bezpośrednimi przekierowaniami wywołującymi wbudowane metody na <tt>self.data</tt>.
# The rest of the methods are straightforward, redirecting the calls to the built-in methods on self.data.
Note
In versions of Python prior to 2.2, you could not directly subclass built-in datatypes like strings, lists, and dictionaries. To compensate for this, Python comes with wrapper classes that mimic the behavior of these built-in datatypes: UserString, UserList, and UserDict. Using a combination of normal and special methods, the UserDict class does an excellent imitation of a dictionary. In Python 2.2 and later, you can inherit classes directly from built-in datatypes like dict. An example of this is given in the examples that come with this book, in fileinfo_fromdict.py.
 
{{Infobox|
In Python, you can inherit directly from the dict built-in datatype, as shown in this example. There are three differences here compared to the UserDict version.
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>.
Example 5.11. Inheriting Directly from Built-In Datatype dict
}}
 
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>.
1 The first difference is that you don't need to import the UserDict module, since dict is a built-in datatype and is always available. The second is that you are inheriting from dict directly, instead of from UserDict.UserDict.
# 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.
2 The third difference is subtle but important. Because of the way UserDict works internally, it requires you to manually call its __init__ method to properly initialize its internal data structures. dict does not work like this; it is not a wrapper, and it requires no explicit initialization.
 
<noinclude>