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

Usunięta treść Dodana treść
Sasek (dyskusja | edycje)
Nie podano opisu zmian
Linia 17:
# Metodę <tt>__init__</tt> nadpisaliśmy w klasie <tt>FileInfo</tt>. Zauważmy, że lista argumentów w klasie przodka jest różna niż w klasie potomka. Jest ok. Każda podklasa może mieć własny zbiór argumentów, pod warunkiem, że metody przodka będą wywoływane z poprawnymi argumentami. Tutaj klasa przodka posiada możliwość zdefiniowania początkowych wartości (dzięki przekazaniu słownika w argumencie <tt>dict</tt>), jednak której klasa <tt>FileInfo</tt> nie wykorzystuje.
# Python wspiera właściwości (zwane polami w Javie i PowerBuilderze). Właściwości to kawałki danych przechowywane w konkretnej instancji klasy. W tym przypadku, każda instancja klasy <tt>UserDict</tt> będzie posiadać właściwość <tt>data</tt>. By odwołać się do tego pola z kodu spoza klasy, dodajemy z przodu nazwę instancji - instancja.data, w ten sam sposób jak odwołujemy się do funkcji poprzez nazwę modułu w jakim się znajduje. By odwołać się do właściwości z wnętrza klasy, używamy <tt>self</tt>. Zazwyczaj wszystkie właściwości są inicjalizowane sensownymi wartościami w metodzie <tt>__init__</tt>. Jednak nie jest to wymagane, gdyż właściwości tak jak zmienne lokalne są tworzone gdy pierwszy raz przypisuje się do nich wartość.
# 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.
# The update method is a dictionary duplicator: it copies all the keys and values from one dictionary to another. This does not clear the target dictionary first; if the target dictionary already has some keys, the ones from the source dictionary will be overwritten, but others will be left untouched. Think of update as a merge function, not a copy function.
# 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.
# This is a syntax you may not have seen before (I haven't used it in the examples in this book). It's an if statement, but instead of having an indented block starting on the next line, there is just a single statement on the same line, after the colon. This is perfectly legal syntax, which is just a shortcut you can use when you have only one statement in a block. (It's like specifying a single statement without braces in C++.) You can use this syntax, or you can have indented code on subsequent lines, but you can't do both for the same block.
Uwaga!
Note
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.
Java and Powerbuilder support function overloading by argument list, i.e. one class can have multiple methods with the same name but a different number of arguments, or arguments of different types. Other languages (most notably PL/SQL) even support function overloading by argument name; i.e. one class can have multiple methods with the same name and the same number of arguments of the same type but different argument names. Python supports neither of these; it has no form of function overloading whatsoever. Methods are defined solely by their name, and there can be only one method per class with a given name. So if a descendant class has an __init__ method, it always overrides the ancestor __init__ method, even if the descendant defines it with a different argument list. And the same rule applies to any other method.
 
Note
Uwaga!
Guido, the original author of Python, explains method overriding this way: "Derived classes may override methods of their base classes. Because methods have no special privileges when calling other methods of the same object, a method of a base class that calls another method defined in the same base class, may in fact end up calling a method of a derived class that overrides it. (For C++ programmers: all methods in Python are effectively virtual.)" If that doesn't make sense to you (it confuses the hell out of me), feel free to ignore it. I just thought I'd pass it along.
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ć.
 
 
Caution
Always assign an initial value to all of an instance's data attributes in the __init__ method. It will save you hours of debugging later, tracking down AttributeError exceptions because you're referencing uninitialized (and therefore non-existent) attributes.