Zanurkuj w Pythonie/Metody specjalne: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Piotr (dyskusja | edycje)
mNie podano opisu zmian
Piotr (dyskusja | edycje)
tłumaczenie
Linia 1:
{{Podświetl|py}}
== Pobieranie i ustawianie elementów ==
 
Linia 38 ⟶ 39:
# Ta linia wygląda jak użycie słownika. Tylko, że <tt>f</tt> jest obiektem klasy próbującej udawać słownik a metoda <tt>__stitem__</tt> jest ważną częścią tej maskarady. Ta linia kodu powoduje właściwie wywołanie <tt>f.__setitem__("genre", 32)</tt>.
 
<tt>__setitem__</tt> jest metodą specjalną, ponieważ Python wywołuje ją za Ciebie, ale ciągle jest metodą klasy. Tak łatowłatwo, jak zdefiniowałeś ją w klasie <tt>UserDict</tt>, możesz ją przedefiniować w klasach pochodnych i zasłonić metodę klasy podstawowej. To pozwala Ci definiować klasy, które czasami zachowują się jak zwykły słownik ale potrafią coś więcej.
 
Koncepcja ta jest prostotą całego szkieletu, który analizujemy w tym rozdziale. Każdy plik może posiadać własną klasę obsługi, która wie, w jaki sposób pobrać dane z różnych typów plików. Natychmiast po pobraniu niektórych atrybutów (jak nazwa pliku i lokacja), które znamy, klasa obsługi będzie wiedziała, jak otrzymać dalsze atrybuty automatycznie. Możemy to zrobić poprzez nadpisanie metody <tt>__setitem__</tt> method, sprawdzenie poszczególnych kluczy i wykonywanie dodatkowych operacji, jeśli dany klucz zostanie znaleziony.
This concept is the basis of the entire framework you're studying in this chapter. Each file type can have a handler class that knows how to get metadata from a particular type of file. Once some attributes (like the file's name and location) are known, the handler class knows how to derive other attributes automatically. This is done by overriding the __setitem__ method, checking for particular keys, and adding additional processing when they are found.
 
ForNa example,przykład <tt>MP3FileInfo</tt> is a descendantjest ofpotomkiem <tt>FileInfo</tt>. WhenKiedy anw <tt>MP3FileInfo's</tt> nameustawiamy isklucz set<tt>"name"</tt>, itnie doesn'ttylko justustawiamy setsam theklucza <tt>"name key"</tt> (likejak theto ancestorrobi FileInfojego doesprzodek <tt>FileInfo</tt>);, itlecz also lookstakże inpatrzymy thedo filesamego itselfpliku forna tagi MP3 tagsi anddodajemy populatespełny azbiór wholekluczy. setPoniższy ofprzykład keys. The nextpokazuje, examplew showsjaki howsposób thisto worksdziała.
 
'''ExamplePrzykład 5.14. OverridingNadpisywanie metody <tt>__setitem__</tt> w inklasie <tt>MP3FileInfo</tt>'''
def __setitem__(self, key, item): #(1)
if key == "name" and item: #(2)
Linia 50 ⟶ 51:
FileInfo.__setitem__(self, key, item) #(4)
 
# Zauważmy, że <tt>__setitem__</tt> jest definiowany w identyczny sposób, jak w klasie przodka. Jest to ważne, ponieważ Python będzie wywoływał tę metodą oczekując odpowiedniej liczby argumentów.(Ściśle mówiąc, nazwy argumentów nic nie znaczą, ważna jest ich ilość.)
# Notice that this __setitem__ method is defined exactly the same way as the ancestor method. This is important, since Python will be calling the method for you, and it expects it to be defined with a certain number of arguments. (Technically speaking, the names of the arguments don't matter; only the number of arguments is important.)
# W tym miejscu jest klucz klasy całej klasy <tt>MP3FileInfo</tt>: jeśli przypisujesz pewną wartość do klucza <tt>"name"</tt>, chcesz wykonać dodatkowo pewne operacje.
# Here's the crux of the entire MP3FileInfo class: if you're assigning a value to the name key, you want to do something extra.
# Dodatkowe operacje dla klucza <tt>"name"</tt> zawarte są w metodzie <tt>__parse</tt>. Jest to inna metoda klasy <tt>MP3FileInfo</tt> i kiedy ją wywołujemy, używamy przy tym zmiennej <tt>self</tt>. Wywołując samo <tt>__parse</tt> odnosimy się do normalnej funkcji, która jest zdefiniowana poza klasą, a tego nie chcemy wykonać. Kiedy natomiast wywołamy <tt>self.__parse</tt> będziemy odnosić się do metody znajdującej się wewnątrz klasy. Nie jest to niczym nowym. W identyczny sposób odnosimy się do atrybutów klasy.
# The extra processing you do for names is encapsulated in the __parse method. This is another class method defined in MP3FileInfo, and when you call it, you qualify it with self. Just calling __parse would look for a normal function defined outside the class, which is not what you want. Calling self.__parse will look for a class method defined within the class. This isn't anything new; you reference data attributes the same way.
# Po wykonaniu tej dodatkowej operacji, chcemy wykonać metodę przodka. Zapamiętaj to co niegdny nie będzie dla ciebie zrobione w Pythonie: musisz to zrobić manualnie. Zwróć uwagę na to, że odwołujemy się bezpośrednio przodka, czyli <tt>FileInfo</tt>, chociaż on nie posiada żadnej metody o nazwie <tt>__setitem__</tt>. Jednak wszystko jest w porządku, ponieważ Python będzie szedł po przodkach jeszcze wyżej dopóki nie znajdzie klasy, która posiada metodę, którą wywołujemy. Tak więc ta linia kodu znajdzie i wywoła metodę <tt>__setitem__</tt> zdefiniowaną w klasie <tt>UserDict</tt>.
# After doing this extra processing, you want to call the ancestor method. Remember that this is never done for you in Python; you must do it manually. Note that you're calling the immediate ancestor, FileInfo, even though it doesn't have a __setitem__ method. That's okay, because Python will walk up the ancestor tree until it finds a class with the method you're calling, so this line of code will eventually find and call the __setitem__ defined in UserDict.
Note
 
{{Infobox|
When accessing data attributes within a class, you need to qualify the attribute name: self.attribute. When calling other methods within a class, you need to qualify the method name: self.method.
Kiedy odwołujesz się do danych zawartych w atrybucie klasy, musisz określić nazwę atrybutu np. <tt>self.attribute</tt>. Podczas wywoływania metody klasy, musisz określić nazwę metody np. <tt>self.method</tt>.
}}
 
'''Przykład 5.15. Ustawianie <tt>"name"</tt> w <tt>MP3FileInfo</tt>'''
'''Example 5.15. Setting an MP3FileInfo's name'''
 
>>> import fileinfo
Linia 75 ⟶ 77:
'comment': 'http://mp3.com/cynicproject'}
 
# First,Najpierw youtworzysz createinstancję an instance ofklasy <tt>MP3FileInfo,</tt> withoutpomijając passingnazwę it a filenamepliku. (YouMożemy cantak getzrobić, awayponieważ with this because theargument <tt>filename</tt> argument of thefunkcji <tt>__init__</tt> method isjest optionalopcjonalny.) SincePonieważ <tt>MP3FileInfo</tt> hasnie noposiada __init__własnej methodmetody of its own<tt>__init__</tt>, Python walksidzie upwyżej thepo ancestordrzewie treeprzodków andi findsznajduje themetodą <tt>__init__</tt> methodw ofklasie <tt>FileInfo</tt>. ThisZ kolei <tt>__init__</tt> w methodtej manuallyklasie callsmanualnie thewykonuje metodę <tt>__init__</tt> methodw ofklasie <tt>UserDict</tt>, anda thenpotem setsustawia theklucz <tt>"name"</tt> key tona <tt>filename</tt>, whichktóry iswynosi <tt>None</tt>, sinceponieważ youpominęliśmy didn'tnazwę pass a filenamepliku. Thus,Ostatecznie <tt>mp3file</tt> initiallypoczątkowo looksprzypomina likesłownik az dictionaryjednym with one key,kluczem <tt>"name"</tt>, whosektórego valuewartość iswynosi <tt>None</tt>.
# NowTeraz therozpoczyna realsię funprawdziwa beginszabawa. SettingUstawiając theklucz <tt>"name"</tt> key ofw <tt>mp3file</tt> triggerspowoduje thewywołanie metody <tt>__setitem__</tt> method onklasy <tt>MP3FileInfo</tt> (notnie <tt>UserDict</tt>), whichktóra noticeszauważa, thatże you'reustawiamy setting theklucz <tt>"name"</tt> keyz withprawdziwą awartością reali value and callswywołuje <tt>self.__parse</tt>. AlthoughChociaż youjeszcze haven'tnie tracedśledziliśmy throughdziałania themetody <tt>__parse method yet</tt>, youmożemy canpo seewyjściu fromzobaczyć, theże outputustawia thatona itkilka setsinnych severalkluczy other keys:jak <tt>"album"</tt>, <tt>"artist"</tt>, <tt>"genre"</tt>, <tt>"title"</tt>, <tt>"year"</tt>, andczy też <tt>"comment"</tt>.
# ModifyingZmieniając theklucz <tt>"name"</tt> keybędziemy willwykonywali goten throughsam theproces same process again:podobnie. Python callswywoła <tt>__setitem__</tt>, whichktóry następnie callswywoła <tt>self.__parse</tt>, whicha setsten allustawi thewszystkie otherinne keysklucze.
 
<noinclude>