Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00252 007759 10468035 na godz. na dobę w sumie
Python. Wprowadzenie - książka
Python. Wprowadzenie - książka
Autor: , Liczba stron: 368
Wydawca: Helion Język publikacji: polski
ISBN: 83-7197-596-1 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> python - programowanie
Porównaj ceny (książka, ebook, audiobook).
Niniejsza książka stanowi wprowadzenie do języka Python. Jest to popularny język programowania obiektowego, używany zarówno w programach działających samodzielnie, jak i w skryptach obejmujących różne dziedziny zastosowań. Python jest bezpłatny, przenośny, bardzo wydajny i wyjątkowo łatwy w użyciu. Bez względu na to, czy ktoś jest nowicjuszem w programowaniu, czy też profesjonalistą, celem tej książki jest szybkie zapoznanie go z istotą języka Python.

Tekst niniejszej książki obejmuje podstawy języka Python; celowo zawęziliśmy jej zakres tematyczny, mając na uwadze łatwość korzystania z niej i jej objętość. Mówiąc inaczej: prezentacja materiału koncentruje się wokół zasadniczych koncepcji i czasem bywa odpowiednio uproszczona. Dlatego właśnie niniejsza książka stanowi znakomity opis języka Python, zarówno jeśli chodzi o wprowadzenie, jak i dalsze, bardziej zaawansowane etapy.

Pomimo tak ograniczonego celu książki (a może właśnie dlatego) sądzimy, że będzie ona dla czytelnika pierwszą wielką lekturą na temat programowania w języku Python. Można się z niej nauczyć wszystkiego, co jest potrzebne w początkowej fazie samodzielnego tworzenia przydatnych programów i skryptów w Pythonie. Po zakończeniu lektury Czytelnik nie tylko będzie znał sam język, ale także będzie wiedział, jak go zastosować w codziennych zadaniach. Książka daje także dobre przygotowanie do podjęcia bardziej zaawansowanych tematów, które programista spotka w swojej praktyce.

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

IDZ DO IDZ DO PRZYK£ADOWY ROZDZIA£ PRZYK£ADOWY ROZDZIA£ SPIS TRE(cid:140)CI SPIS TRE(cid:140)CI Python KATALOG KSI¥flEK KATALOG KSI¥flEK KATALOG ONLINE KATALOG ONLINE ZAM(cid:211)W DRUKOWANY KATALOG ZAM(cid:211)W DRUKOWANY KATALOG TW(cid:211)J KOSZYK TW(cid:211)J KOSZYK DODAJ DO KOSZYKA DODAJ DO KOSZYKA CENNIK I INFORMACJE CENNIK I INFORMACJE ZAM(cid:211)W INFORMACJE ZAM(cid:211)W INFORMACJE O NOWO(cid:140)CIACH O NOWO(cid:140)CIACH ZAM(cid:211)W CENNIK ZAM(cid:211)W CENNIK CZYTELNIA CZYTELNIA FRAGMENTY KSI¥flEK ONLINE FRAGMENTY KSI¥flEK ONLINE Autorzy: Mark Lutz, David Ascher T‡umaczenie: Zygmunt Wereszczyæski ISBN: 83-7197-596-1 Tytu‡ orygina‡u: Format: B5, stron: 365 Learning Python Niniejsza ksi„¿ka stanowi wprowadzenie do jŒzyka Python. Jest to popularny jŒzyk programowania obiektowego, u¿ywany zar(cid:243)wno w programach dzia‡aj„cych samodzielnie, jak i w skryptach obejmuj„cych r(cid:243)¿ne dziedziny zastosowaæ. Python jest bezp‡atny, przeno(cid:156)ny, bardzo wydajny i wyj„tkowo ‡atwy w u¿yciu. Bez wzglŒdu na to, czy kto(cid:156) jest nowicjuszem w programowaniu, czy te¿ profesjonalist„, celem tej ksi„¿ki jest szybkie zapoznanie go z istot„ jŒzyka Python. Tekst niniejszej ksi„¿ki obejmuje podstawy jŒzyka Python; celowo zawŒzili(cid:156)my jej zakres tematyczny, maj„c na uwadze ‡atwo(cid:156)(cid:230) korzystania z niej i jej objŒto(cid:156)(cid:230). M(cid:243)wi„c inaczej: prezentacja materia‡u koncentruje siŒ wok(cid:243)‡ zasadniczych koncepcji i czasem bywa odpowiednio uproszczona. Dlatego w‡a(cid:156)nie niniejsza ksi„¿ka stanowi znakomity opis jŒzyka Python, zar(cid:243)wno je(cid:156)li chodzi o wprowadzenie, jak i dalsze, bardziej zaawansowane etapy. Pomimo tak ograniczonego celu ksi„¿ki (a mo¿e w‡a(cid:156)nie dlatego) s„dzimy, ¿e bŒdzie ona dla czytelnika pierwsz„ wielk„ lektur„ na temat programowania w jŒzyku Python. Mo¿na siŒ z niej nauczy(cid:230) wszystkiego, co jest potrzebne w pocz„tkowej fazie samodzielnego tworzenia przydatnych program(cid:243)w i skrypt(cid:243)w w Pythonie. Po zakoæczeniu lektury Czytelnik nie tylko bŒdzie zna‡ sam jŒzyk, ale tak¿e bŒdzie wiedzia‡, jak go zastosowa(cid:230) w(cid:160) codziennych zadaniach. Ksi„¿ka daje tak¿e dobre przygotowanie do podjŒcia bardziej zaawansowanych temat(cid:243)w, kt(cid:243)re programista spotka w swojej praktyce. Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl 78(cid:4)4 / /  Część I ./q(cid:8)+ ...................................................5.................. 15 Rozdział 1. /6;7/63 /  Dlaczego właśnie Python?...................................................w...................................................w.17 Jak należy uruchamiać programy w języku Python?...................................................w............ 24 Pierwsze spojrzenie na pliki modułowe ...................................................w............................... 30 Szczegóły związane z konfiguracją języka Python ...................................................w.............. 32 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ ...... 36 ........... 37 Rozdział 2. $434/6+836 /  Struktura programu w języku Python...................................................w................................... 39 Przyczyny stosowania typów wbudowanych ...................................................w....................... 39 Liczby ...................................................w...................................................w................... Łańcuchy...................................................w...................................................w................. Listy ...................................................w...................................................w.................... Słowniki ...................................................w...................................................w................. Krotki ...................................................w...................................................w................... Pliki...................................................w...................................................w.................... Ogólne właściwości obiektów ...................................................w.............................................. 69 „Niespodzianki” typów wbudowanych ...................................................w................................ 75 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ ............. 41 ........... 48 ............... 56 ............ 61 .............. 65 ................ 67 ...... 77 ........... 78  #4786/- Rozdział 3. 27869-/43.78+;3;/ /  Przypisanie...................................................w...................................................w.............. Wyrażenia ...................................................w...................................................w................ Instrukcja print...................................................w...................................................w......... Testy if ...................................................w...................................................w................. Pętle while...................................................w...................................................w.............. Pętle for...................................................w...................................................w................ Niespodzianki spotykane w kodzie ...................................................w.................................... 102 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ ........... 82 .......... 85 .......... 86 .............. 87 ............ 94 .............. 97 .... 103 ......... 104 Rozdział 4. 92-/ /  Dlaczego należy stosować funkcje? ...................................................w................................... 107 Podstawy funkcji.....................................w...................................................w....................... Zakresy działania w funkcjach ...................................................w........................................... 111 Przekazywanie argumentów ...................................................w............................................... 114 Informacje dodatkowe ...................................................w...................................................w.....120 Niespodzianki w funkcjach...................................................w................................................. 126 Podsumowanie ...................................................w...................................................w............. .... 131 ......... 132 Ćwiczenia...................................................w...................................................w................ ..... 108 Rozdział 5. 3.9o /  Dlaczego używa się modułów? ...................................................w.......................................... 135 Podstawowe informacje o modułach ...................................................w.................................. 136 Pliki modułowe są przestrzeniami nazw ...................................................w............................ 138 Model importu ...................................................w...................................................w............ Ponowne ładowanie modułów...................................................w............................................ 142 Informacje dodatkowe ...................................................w...................................................w.....144 Modułowe niespodzianki...................................................w...................................................w. 151 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ .... 156 ......... 156 ..... 140 Rozdział 6. +7 /  Dlaczego należy używać klas? ...................................................w........................................... 159 Podstawy działania klas...................................................w...................................................w.. . 160 Używanie instrukcji class ...................................................w...................................................w167 Zastosowania metod klasy...................................................w.................................................. 168 #4786/-  Dziedziczenie i przeszukiwanie drzew przestrzeni nazw...................................................w... 169 Przeciążanie operatorów w klasach ...................................................w.................................... 173 Komplet reguł dla przestrzeni nazw ...................................................w................................... 176 Zastosowania klas w programach...................................................w....................................... 178 Informacje dodatkowe ...................................................w...................................................w.....188 Niespodzianki w klasach ...................................................w...................................................w. 190 .... 196 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ ......... 196 Rozdział 7. 8 /  Dlaczego należy używać wyjątków? ...................................................w.................................. 201 Podstawy działania wyjątków...................................................w............................................. 202 Idiomatyczne określenia wyjątków ...................................................w.................................... 206 Tryby wychwytywania wyjątków...................................................w....................................... 208 Informacje dodatkowe ...................................................w...................................................w.....211 Wyjątkowe niespodzianki...................................................w...................................................w 215 Podsumowanie ...................................................w...................................................w............. Ćwiczenia...................................................w...................................................w................ .... 217 ......... 218 Część II +678;/;2(cid:8)862/...................................................5....221 Rozdział 8. +6(cid:4).+;,9.3;+2/ /  Funkcje wbudowane ...................................................w...................................................w........225 .... 232 Moduły biblioteki ...................................................w...................................................w........ Ćwiczenia...................................................w...................................................w................ ......... 249 Rozdział 9. $43;/+.+2+;(cid:4)9 832  Manipulacja strukturami danych ...................................................w........................................ 251 Manipulacja plikami ...................................................w...................................................w...... Manipulacja programami...................................................w...................................................w. 268 Działanie w Internecie ...................................................w...................................................w... Przykłady większych programów...................................................w....................................... 273 Ćwiczenia...................................................w...................................................w................ ......... 278 .. 257 .. 270  #4786/- Rozdział 10. 723;46316+3;+2++4+-/  System automatycznego zgłaszania skarg...................................................w.......................... 282 Tworzenie interfejsu za pomocą COM: tani rzecznik prasowy ............................................ 287 Edytor elementów formularza danych...................................................w................................ 292 Rozważania o projektowaniu...................................................w.............................................. 297 JPython: szczęśliwy związek języków Python i Java...................................................w......... 298 Inne osnowy i aplikacje ...................................................w...................................................w.. . 305 Ćwiczenia...................................................w...................................................w................ ......... 307 3.+8 ...................................................5..................................... 309 Dodatek A +8/6+o 6..o3;/(cid:4)+ 832  Dodatek B +1+.2/2+;+2/6. 24+8036+  Dodatek C 3;+2+;-/q /  #363;. / /  W rozdziale tym przedstawimy klasę języka Python, czyli twór, który służy do wprowadzania no- wych rodzajów obiektów w Pythonie. Klasy stanowią najważniejsze narzędzie programowania obiektowego, zatem w tym rozdziale omówimy także podstawy tego programowania. Klasy w ję- zyku Python tworzone są za pomocą nie omawianej dotychczas instrukcji class. Obiekty zdefi- niowane za pomocą klas mogą wyglądać bardzo podobnie, jak wbudowane typy, które były już opisywane w tej książce. Na jedną rzecz należy szczególnie zwrócić uwagę: obiektowość języka Python jest całkowicie opcjonalna i nie trzeba używać klas, by rozpocząć pracę w tym języku. Wiele zadań można w rze- czywistości wykonać za pomocą prostszych konstrukcji, takich jak np. funkcje. Klasy okazują się jednak bardzo przydatne w Pythonie i mamy nadzieję, że to udowodnimy. Mają one także swój udział w powszechnie stosowanych narzędziach języka Python, takich jak Tkinter, i większość programistów uważa, że przydaje się tu znajomość klase co najmniej w stopniu podstawowym. Czytelnicy z pewnością pamiętają, że programy wykonują zadania za pomocą „nadziewania”. Mówiąc prościej, klasy są po prostu sposobem definiowania nowych rodzajów nadzienia, które symbolizuje prawdziwe obiekty w dziedzinie tworzonych programów. Załóżmy na przykład, że zdecydowaliśmy się utworzyć hipotetycznego robota robiącego pizzę (wzmianka w rozdziale 4.). Jeśli do tego celu zastosujemy klasy, to możemy wymodelować taką strukturę robota, która będzie bliższa jego rzeczywistemu światu i stosunkom w nim epanującym: Dziedziczenie Roboty wytwarzające pizzę należą do rodzaju robotów ie dlatego mają wszystkie zwyczajne właściwości robotów. Używając określeń z dziedziny proegramowania obiektowego, mówimy, że dziedziczą one właściwości ogólnej kategorii wszystekich robotów. Te wspólne właściwości wprowadzone są tylko raz dla przypadku ogólnego i będeą używane przez wszystkie typy robotów budowanych w przyszłości. Kompozycja Roboty wytwarzające pizzę są w rzeczywistości kolekcjeami komponentów, które działają zespołowo. Aby nasz przykładowy robot był skutecznye, powinien zapewne posiadać ramiona  3.+o +7 do zawijania ciasta, silniki do manewrowania przy piecu itd. W „mowie obiektowej” nasz robot jest przykładem kompozycji: zawiera on inne oebiekty, które uaktywnia do wykonywania ich zadań. Każdy komponent może być zakodowany jako kelasa, definiująca swoje własne zachowanie i zależności. Oczywiście większość z nas nie zarabia na budowaniu robotów do wytwarzania pizzy, lecz ogólne pomysły obiektowego programowania, takie jak np. dziedziczenie i kompozycja, można zastoso- wać w dowolnej aplikacji, która da się rozłożyć na zbiór obiektów. Na przykład typowe systemy interfejsu graficznego są tworzone w postaci zbiorów widżetów (przyciski, etykiety itd.), które są wszystkie rysowane, gdy rysowany jest zawierający je pojemnik (kompozycja). Oprócz tego moż- na samodzielnie utworzyć własne widżety, które będą specjalizowanymi wersjami elementów in- terfejsu o bardziej ogólnych cechach (dziedziczenie). Rozważając to wszystko z perspektywy konkretnego programowania, można stwierdzić, że klasy są jednostką programu języka Python, podobnie jak funkcje i moduły. Stanowią one inną prze- strzeń do umieszczania logiki i danych programu. W rzeczywistości klasy definiują także nową przestrzeń nazw, bardzo podobnie do modułów. W porównaniu z innymi składnikami programu, które były do tej pory omawiane, klasy różnią się trzema cechami o podstawowym znaczeniu, dzięki którym można ich używać podczas budowy nowych obieketów: Istnienie wielu egzemplarzy W przybliżeniu klasy można określić jako wzorce służeące do generowania obiektów. Przy każdym wywołaniu klasy tworzony jest nowy obiekt, peosiadający oddzielną przestrzeń nazw. Jak się przekonamy, każdy obiekt wygenerowany z klasey ma dostęp do atrybutów tej klasy i otrzymuje swoją własną przestrzeń nazw, w której bęedą przechowywane dane specyficzne dla tego obiektu. Przystosowanie do specyficznych potrzeb za pomocą dmziedziczenia Klasy obsługują także dziedziczenie w sensie obiektoweym; można je rozszerzać za pomocą modyfikacji ich atrybutów poza samą klasą. Mówiąc bardeziej ogólnie, klasy mogą tworzyć hierarchie przestrzeni nazw, w których definiują nazewy przeznaczone do użytku w obiektach utworzonych z klas w danej hierarchii. Przeciążanie operatora Dzięki specjalnym metodom protokołowym klasy mogą defieniować obiekty odpowiadające tym rodzajom działań, które były już pokazane podczeas działania na typach wbudowanych. Na przykład obiekty utworzone za pomocą klas mogą być ecięte, łączone, indeksowane itd. Jak się wkrótce przekonamy, w Pythonie możliwe są róeżne sztuczki, dzięki którym klasy mogą przejmować każdą operację na typach wbudowanych. Czytelnikowi, nie mającemu wcześniej styczności z programowaniem obiektowym, klasy mogą się wydawać skomplikowane, szczególnie gdy wszystkie informacje na ich temat są przekazane w jednej dawce. Aby ułatwić zrozumienie tych zagadnień, rozpoczniemy więc od krótkiego pokazu klas w działaniu, podkreślając trzy wyróżniające je cechy, o których była mowa poprzednio. Klasy języka Python w swojej podstawowej postaci są łatwe do zrozumienia, zaś szczegółami zajmiemy się już za chwilę. 3.78+;.+o+2++7  +78;36;///1/4+63,/8(cid:20); Jak już wspomnieliśmy pod koniec rozdziału 5., poświęconego modułom, klasy są przeważnie prze- strzeniami nazw, podobnie jak moduły. W odróżnieniu od modułów, w klasach występuje także tworzenie wielokrotnych kopii, dziedziczenie przestrzeni nazw i przeciążanie operatorów. Zajmiemy się teraz pierwszym z tych zagadnień. Aby zrozumieć mechanizm tworzenia wielokrotnych kopii, należy sobie uświadomić, że istnieją dwa rodzaje obiektów w modelu programowania obiektowego języka Python: obiekty klasy i egzem- plarze obiektów. Obiekty klasy zapewniają domyślne zachowanie i służą jako generatory dla egzem- plarzy obiektów. Egzemplarze obiektów są rzeczywistymi obiektami, które są przetwarzane przez programy. Każdy z tych egzemplarzy jest przestrzenią nazw, rządzącą się własnymi prawami, lecz dziedziczy nazwy z klasy (czyli ma do nich dostęp), z której powstał. Obiekty klasy pochodzą z in- strukcji, zaś egzemplarze obiektów pochodzą z wywołań. Przy każdym wywołaniu klasy uzyskuje się nowy egzemplarz. W tym momencie należy się skoncentrować, ponieważ przedstawimy najważniej- sze zagadnienia, dotyczące programowania obiektowego we języku Python. ,/8+7+4/;2+.32/+-3;+2/ Instrukcja class tworzy obiekt klasy i przypisuje mmu nazwę Podobnie jak def, instrukcja class języka Python jest instrukcją wykonywalną. Gdy zostanie ona uruchomiona, wtedy utworzy nowy obiekte klasy i przypisze mu nazwę podaną w nagłówku class. Przypisania wewnątrz instrukcji class tworzą atrybumty klasy Podobnie jak w modułach, przypisania w instrukcji class tworzą atrybuty w obiekcie klasy. Atrybuty klasy są dostępne za pomocą kwalifikacji nazwe (obiekt.nazwa). Atrybuty klasy eksportują stan i zachowanie obiektum Atrybuty obiektu klasy przechowują informację o jego setanie i zachowaniu, które mają być współdzielone przez wszystkie egzemplarze obiektów eutworzonych w danej klasie. Instrukcje def wewnątrz instrukcji class generują metody przetwarzające egzemplarze. 1/4+6/3,/8(cid:27);71/2/63;+2/+7 Wywołanie obiektu klasy (podobnie jak wywołuje się funmkcję) tworzy nowy egzemplarz obiektu Przy każdym wywołaniu klasa generuje i zwraca nowy eegzemplarz obiektu. Każdy egzemplarz obiektu dziedziczy atrybuty klasy mi otrzymuje swoją własną przestrzeń nazw Egzemplarze obiektów generowane z klas są nowymi przesetrzeniami nazw. Początkowo są one puste, ale dziedziczą atrybuty obiektu klasy, z której zostały wygenerowane. Przypisania do siebie w metodach tworzą atrybuty damnego egzemplarza Pierwszy argument w funkcjach metody klasy (nazywany eumownie self) odwołuje się do przetwarzanego egzemplarza obiektu. Przypisania do aetrybutów self tworzą lub modyfikują dane w egzemplarzu, a nie w klasie.  6o+. 3.+o +7 Pomijając kilka szczegółów, to już wszystko, co dotyczy obiektowości języka Python. Zajmiemy się teraz przykładem, ponieważ chcemy pokazać praktyczne zastosowanie tych idei. Najpierw zde- finiujemy klasę nazwaną FirstClass, używając instrukcji class: class FirstClass: # definiowanie obiektu klasy ... def setdata(self, value): # definiowanie metod klasy ... self.data = value # self jest egzemplarzem ... def display(self): ... print self.data # self.data (dla danego egzemplarza) Podobnie jak inne instrukcje złożone, instrukcja class rozpoczyna się od wiersza nagłówkowego, który zawiera nazwę klasy. Po wierszu nagłówkowym następuje ciało, składające się z zagnież- dżonych i wciętych instrukcji. W naszym przykładzie zagnieżdżone są instrukcje def, definiujące funkcje. Funkcje te określają zachowanie, które klasa ma eksportować. Jak już opisywaliśmy, instrukcja def jest przypisaniem, które w tym przypadku przypisuje wartości do nazw w zakresie instrukcji class i w ten sposób generuje atrybuty klasy. Funkcje wewnątrz klasy są zwykle nazy- wane metodami. Są to zwyczajne funkcje, określane za pomocą instrukcji def, chociaż przy wywołaniu ich pierwszy argument automatycznie otrzymuje egzemplarz obiektu dla którego metoda została wywołana. Oto para przykładowych egzemplarzy: x = FirstClass() # tworzenie dwóch egzemplarzy y = FirstClass() # każdy jest nową przestrzenią nazw Za pomocą takiego wywołania klasy generujemy egzemplarze obiektów, które są po prostu prze- strzeniami nazw, otrzymującymi od razu atrybuty klasy. Mówiąc poprawnie: mamy tu trzy obiekty — dwa egzemplarze i klasę — lecz w rzeczywistości mamy trzy powiązane przestrzenie nazw (patrz rysunek 6.1). Posługując się terminologią programowania obiektowego, mówimy, że x jest klasy FirstClass, podobnie jak y. Egzemplarze są początkowo puste, lecz mają powiązania z klasą; jeśli kwalifikujemy egzemplarz za pomocą nazwy atrybutu w obiekcie klasy, to Python pobiera nazwę z klasy (chyba że ta nazwa już znajduje się we egzemplarzu): x.setdata( King Arthur ) # wywołanie metody: self jest x lub y y.setdata(3.14159) # uruchomienie: FirstClass.setdata(y, 3.14159) Ani x, ani y nie mają własnej metody setdata; jeśli atrybut nie istnieje w egzemplarzu, Python śledzi powiązanie z egzemplarza do klasy. I to jest prawie wszystko, co chcieliśmy tu pokazać na temat dziedziczenia w języku Python: występuje ono w czasie kwalifikacji atrybutu i powoduje wyszukiwanie nazw w powiązanych obiektach (poprzez śledzenie powiązań is-a, jak to pokaza- no na rysunku 6.1). Wartość przekazana w funkcji setdata klasy FirstClass jest przypisywana do self.data. W ramach danej metody self automatycznie odwołuje się do egzemplarza, który jest przetwa- rzany (x lub y), a więc przypisania zachowują wartości w przestrzeniach nazw egzemplarzy, a nie klasy (wyjaśnia to, w jaki sposób powstały nazwy data pokazane na rysunku 6.1). Klasy gene- rują wiele egzemplarzy, zatem metody muszą korzystać z argumentu self, by uzyskać dostęp do egzemplarza, który ma być przetwarzany. Gdy wywołamy metodę display klasy, chcąc wydru- kować self.data, to przekonamy się, że jest ona różna w każdym egzemplarzu. Z drugiej stro- ny, display jest takie samo w x i y, ponieważ pochodzi (jest dziedziczone) z klasy: 3.78+;.+o+2++7  Rysunek 6.1. Klasy i egzemplarze są powiązanymi obi.ektami przestrzeni nazw x.display() # self.data różni się w każdym egzwemplarzu King Arthur y.display() 3.14159 Zachowaliśmy tu obiekty różnego typu w członku data (łańcuch i liczbę zmiennoprzecinkową). Podobnie jak w innych sytuacjach, Python nie potrzebuje deklaracji typu dla atrybutów egzempla- rza (zwanych czasem członkami). Atrybuty są powoływane do istnienia dopiero po pierwszym przypisaniu im wartości, podobnie jak w przypadku prostych zmiennych. W rzeczywistości atry- buty egzemplarza można zmieniać albo w samej klasie za pomocą przypisania do self w meto- dach, albo poza klasą za pomocą przypisania do istnieejącego egzemplarza obiektu: x.data = Nowe dane # można pobrać lub ustawić atrybuty x.display() # także na zewnątrz klasy Nowe dane #4/-++-++7;/.o91./.-/2+ W odróżnieniu od modułów, klasy pozwalają na modyfikację także za pomocą wprowadzenia no- wych komponentów (klas podrzędnych), a nie tylko za pomocą modyfikacji istniejących kompo- nentów na miejscu. Pokazaliśmy już, że egzemplarze obiektów wygenerowane z klasy dziedziczą jej atrybuty. Python pozwala również, by klasy dziedziczyły z innych klas. Toruje to drogę dla nowych struktur zwanych osnowami. Są to hierarchie klas, które specjalizują swoje zachowanie za pomocą zastępowania atrybutów w klasach leżących niżej w hierarchii. Główne idee całej tej ma- szynerii są następujące: W nagłówku klasy podawane są w nawiasach klasy nadrzęmdne Aby dziedziczenie atrybutów z innej klasy było możleiwe, należy po prostu wpisać ją w nawiasach w nagłówku instrukcji klasy. Klasa, która dziedziczye, jest nazywana klasą podrzędną, zaś klasa, z której pochodzi dziedziczenie, jest klasą nadrzędną. Klasy dziedziczą atrybuty ze swoich klas nadrzędnycmh Podobnie jak w przypadku egzemplarza, klasa otrzymueje natychmiast wszystkie nazwy zdefiniowane w swojej klasie nadrzędnej. Nazwy te są znajdowane przez Python automatycznie podczas kwalifikacji, jeśli nie istnieją w klasie poderzędnej.  3.+o +7 Egzemplarze dziedziczą atrybuty ze wszystkich dostęmpnych klas Egzemplarze otrzymują nazwy z klasy, z której są genereowane, oraz ze wszystkich klas nadrzędnych tej klasy. Podczas wyszukiwania nazwy Peython sprawdza egzemplarz, następnie jego klasę, a później jej wszystkie klasy nadrzędne.e Zmiany działania są realizowane za pomocą wprowadzanmia klas podrzędnych, a nie przez modyfikacje klas nadrzędnych Po ponownym zdefiniowaniu w klasach podrzędnych nazew występujących w klasach nadrzędnych, klasy podrzędne zastępują odziedziczone środowisko nowym. 6o+. Nasz kolejny przykład korzysta z poprzedniego. Zdefiniujmy teraz nową klasę SecondClass, która dziedziczy wszystkie nazwy z FirstClass i dodaje swoją własną nazwę: class SecondClass(FirstClass): # dziedziczy setdata ... def display(self): # zmienia display ... print Obecne dane = s self.data SecondClass definiuje ponownie metodę display, by używać innego formatu wyświetlania. Ponieważ SecondClass definiuje atrybut o tej samej nazwie, to zastępuje nim atrybut display w klasie FirstClass. Proces dziedziczenia rozpoczyna od przeszukiwania egzemplarzy, następnie obiektu klasy i klas nadrzędnych i zatrzymuje się po pierwszym wystąpieniu szukanej nazwy atrybutu. Ponieważ nazwa display zostanie znaleziona w SecondClass przed jej znale- zieniem w FirstClass, mówimy, że SecondClass zastępuje display z FirstClass swoim własnym atrybutem. Innymi słowy, SecondClass dokonuje specjalizacji FirstClass, zmieniając działanie metody display. Z drugiej strony, SecondClass (i utworzone z niej egzemplarze) nadal dziedziczą dosłownie metodę setdata z FirstClass. Na rysunku 6.2 po- kazano użyte tutaj przestrzenie nazw. Utwórzmy teraez przykładowy egzemplarz: Rysunek 6.2. Specjalizacja wprowadzona za pomocą za.stąpienia dziedziczonych nazw z = SecondClass() z.setdata(42) # setdata znalezione w FirstClass z.display() # znajduje zastąpioną metodę w SecondClwass Obecne dane = 42 3.78+;.+o+2++7  Podobnie jak poprzednio, tworzymy egzemplarz obiektu klasy SecondClass, wywołując ją. Wywołanie setdata nadal działa na wersji z FirstClass, lecz tym razem atrybut display pochodzi od SecondClass i wyświetla inny komunikat. Tutaj bardzo ważna informacja na temat programowania obiektowego: specjalizacja wprowadzona w SecondClass jest całkowi- cie zewnętrzna w stosunku do FirstClass i nie ma wpływu na istniejące lub przyszłe obiekty FirstClass, takie jak obiekt x z poprzedniego przykładu: x.display() # x jest nadal egzemplarzem FirstClass (stary komwunikat) Nowe dane Oczywiście jest to sztuczny przykład, lecz regułą jest, że często klasy obsługują rozszerzenia i po- nowne użycie elementów lepiej, niż to czynią funkcje lub moduły. Wynika to właśnie stąd, że zmiany mogą być dokonywane na elementach zewnętrznyche (w klasach podrzędnych). +73146/7o+2+34/6+836(cid:29)+ 832 Na zakończenie tego wykładu spójrzmy na trzecią główną właściwość klas: przeciążanie operato- rów. Mówiąc prosto, dzięki przeciążaniu operatorów obiekty wprowadzone za pomocą klas mogą być poddawane takim operacjom, którym podlegają wbudowane typy: dodawaniu, wycinaniu, drukowaniu, kwalifikacji itd. Można wprawdzie wprowadzić całe zachowanie obiektu, stosując funkcje metod, lecz przeciążanie operatorów pozwala na większą integrację tych obiektów z mo- delem obiektowym języka Python. I więcej: przeciążanie operatorów powoduje, że samodzielnie utworzone obiekty zachowują się tak, jak wbudowane, zatem sprzyja to rozwojowi interfejsów obiektowych, które są bardziej zwarte i łatwiejsze do opanowania. A oto główne wnioski wynika- jące z tych rozważań: Metody o nazwach takich jak __X__ są specjalnymi punktammi zaczepienia Przeciążanie operatorów w języku Python odbywa się eza pomocą specjalnie nazwanych metod, które przesłaniają operacje. Takie metody są wywoływane automatycznie, gdy język Pmython rozwija operatory Jeśli jakiś obiekt dziedziczy np. metodę __add__, to jest ona wywoływana wtedy, gdy ten obiekt pojawi się w wyrażeniu +. Klasy mogą zastępować większość wbudowanych operacji mna typach Istnieją dziesiątki nazw metod operatorów specjalnyche, które mogą przechwytywać prawie wszystkie operacje dostępne dla typów wbudowanych. Operatory pozwalają na integrację klas z modelem obmiektowym języka Python Dzięki przeciążaniu operacji na typach, obiekty zdefieniowane przez użytkownika i wprowadzone za pomocą klas zachowują się tak, jak obiekty wbudowane. 6o+. Przejdźmy teraz do innego przykładu. Definiujemy klasę podrzędną w stosunku do SecondClass, która wprowadza trzy atrybuty specjalne: __init__, wywoływane podczas tworzenia nowego egzemplarza obiektu (self jest nowym obiektem z ThirdClass) oraz __add__ i __mul__, wywoływane wtedy, gdy egzemplarz z ThirdClass pojawia się odpowiednio w wyrażeniach + i *:  3.+o +7 class ThirdClass(SecondClass): # is-a SecondClass ... def __init__(self, value): # działa na ThirdClass(value) ... self.data = value ... def __add__(self, other): # działa na self + other ... return ThirdClass(self.data + other) ... def __mul__(self, other): ... self.data = self.data * other # działa na self * other a = ThirdClass( abc ) # nowe wywołanie __init__ a.display() # metoda odziedziczona Obecne dane = abc b = a + xyz # nowe wywołanie __add__: tworzy nowy egzemplwarz b.display() Obecne dane = abcxyz a * 3 # nowe wywołanie __mul__: zmienia egzwemplarz a.display() Obecne dane = abcabcabc Klasa ThirdClass jest klasy SecondClass, zatem jej egzemplarze dziedziczą display z SecondClass. Wywołanie generujące egzemplarz klasy ThirdClass przekazuje następnie argument ( abc ). Jest on przekazywany do argumentu value w konstruktorze __init__ i przypisywany tam do self.data. Potem obiekty ThirdClass mogą pokazywać się w wyra- żeniach + i *. Python przekazuje egzemplarz obiektu z lewej strony do argumentu self, zaś wartość z prawej strony do other (patrz rysunek 6.3). Rysunek 6.3. Odwzorowanie operatorów w metodach specj.alnych Metody specjalne, takie jak __init__ i __add__, są dziedziczone przez klasy podrzędne i eg- zemplarze, podobnie jak inne nazwy przypisane w instrukcji klasy. Zauważmy, że metoda __add__ tworzy nowy obiekt (wywołując ThirdClass z wynikową wartością), zaś __mul__ modyfi- kuje aktualny egzemplarz obiektu w miejscu (ponownie przypisując atrybut self). Operator * tworzy nowy obiekt, gdy zastosuje się go do typów wbudowanych, takich jak liczby i listy, lecz w obiektach klasy można go interpretować dowolnie1. 1 Raczej nie należy tego robić (jeden z recenzentów dloszedł aż do tego, że nazwał ten przykład „diabelstlwo”!). Powszechna praktyka mówi, że operatory przeciążone powlinny działać w taki sam sposób, jak działają operatory wbudowane. W naszym przypadku oznacza to, żel metoda __mul__ powinna zwrócić w wyniku raczej nowy obiekt, niż zmieniać w miejscu jego egzemplarz (self). Być może w lepszym stylu byłoby użycie metody mul, a nie przeciążanie * (np. mul(3) zamiast * 3). Z drugiej strony, praktyki stosowane przez jednych, nie muszą obowiązywać innych. ;+2/27869--+77  Czy wszystko to, co napisaliśmy powyżej, ma sens? Jeśli nie, to nie należy się martwić; po tym krótkim wprowadzeniu zagłębimy się bardziej w szczegóły omawianych zagadnień. Pokazaliśmy już wprawdzie instrukcję class w początkowych przykładach, lecz teraz zrobimy to od strony bardziej formalnej. Podobnie jak w języku C++, instrukcja class jest także głównym narzędziem programowania obiektowego w języku Python. Ale w odróżnieniu od C++, class nie jest jednak deklaracją. Jest ona, tak samo jak def i class, budowniczym obiektów i ukrytym przypisaniem. Po uruchomieniu generuje ona obiekt klasy i zachowuje odwołanie do tego obiektu w nazwie użytej w nagłówku. 378+31(cid:20)2+ Pokazaliśmy już, że class jest instrukcją złożoną, której ciało tworzą wcięte instrukcje umiesz- czone pod wierszem nagłówkowym. Klasy nadrzędne w nagłówku są podawane w nawiasach, występują po nazwie definiowanej klasy i są oddzielone przecinkami. Wpisanie więcej niż jednej klasy nadrzędnej prowadzi do wielokrotnego dziedzicezenia (wyjaśnimy to później w tym rozdziale): class nazwa (superclass,...): # przypisaniew do nazwy data = value # współdzielowne dane klasy def method(self,...): # metody self.member = value # dane egzemwplarzy W instrukcji klasy specjalnie nazwane metody przeciążają operatory; np. podczas tworzenia egzem- plarza obiektu wywoływana jest funkcja o nazwie __init__, jeśli została zdefiniowana. 6o+. Na początku tego rozdziału wspomnieliśmy, że klasy są przeważnie przestrzeniami nazw — na- rzędziem służącym do definiowania nazw (zwanych atrybutami), które eksportują dane i działania do klientów. Zatem w jaki sposób dostajemy się z inestrukcji do przestrzeni nazw? Podobnie jak w modułach, instrukcja zagnieżdżona w treści instrukcji class tworzy atrybuty. Gdy Python uruchamia instrukcję class (a nie wywołanie klasy), to uruchamia kolejno wszystkie jej instrukcje umieszczone w jej ciele, poczynając od góry. Przypisania, które następują w czasie tego procesu, tworzą nazwy w lokalnym zakresie klasy, zaś te nazwy stają się atrybutami w powiązanym obiekcie klasy. Klasy są zatem podobne zarówno do moedułów, jak i do funkcji, ponieważ:  Instrukcje class tworzą zakres lokalny, czyli miejsce, gdzie istniejeą nazwy utworzone przez zagnieżdżone przypisania (podobnie jak w funkcjach).  Nazwy przypisane w instrukcji class stają się atrybutami w obiekcie klasy (podobnie, jak w modułach). Głównym wyróżnikiem klas jest fakt, że ich przestrzenie nazw są także podstawą dziedziczenia w języku Python; atrybuty są pobierane z innych klas tylko wtedy, gdy nie są znalezione w danej klasie lub w egzemplarzu obiektu. Ponieważ class jest instrukcją złożoną, to w jej ciele może  3.+o +7 być zagnieżdżona instrukcja dowolnego rodzaju, np. print, =, if lub def. Pokazaliśmy już, że zagnieżdżona instrukcja def tworzy metodę klasy — inne przypisania także tworzą atrybuty. Załóżmy, że uruchamiamy następującą przykładową klasę: class Subclass(aSuperclass): # definicja klawsy podrzędnej data = mielonka # przypisanie awtrybutu klasy def __init__(self, value): # przypisanie atrywbutu klasy self.data = value # przypisanie watrybutu egzemplarza def display(self): print self.data, Subclass.data # egzempwlarz, klasa Ta klasa zawiera dwie instrukcje def, które dowiązują atrybuty klasy do funkcji metod. Zawiera ona także instrukcję przypisania (=); ponieważ zaś nazwa data jest przypisana wewnątrz instruk- cji class, to istnieje w lokalnym zakresie klasy i staje się atrybutem obiektu tej klasy. Podobnie jak wszystkie pozostałe atrybuty klasy, atrybut data jest dziedziczony i współdzielony przez wszystkie egzemplarze klasy2: x = Subclass(1) # tworzy dwa egzemplarze obiektów y = Subclass(2) # każdy ma swoje własne dane ( data ) x.display(); y.display() # self.data inne, Subclass.data takie same 1 mielonka 2 mielonka Gdy uruchamiamy ten kod, nazwa data istnieje w dwóch miejscach: w egzemplarzach obiektów (utworzonych za pomocą konstruktora __init__) i w klasie, z której są dziedziczone nazwy (utworzonej za pomocą przypisania =). Metoda klasy display wyświetla obydwie wersje, naj- pierw za pomocą kwalifikacji samego egzemplarza, a następnie za pomocą samej klasy. Ponieważ klasy są obiektami posiadającymi atrybuty, to ich nazwy można uzyskać za pomocą kwalifikacji nawet wtedy, gdy nie został wprowadzony egzemplarz. Zapoznaliśmy już Czytelników z funkcjami, zatem możemy powiedzieć, że metody klasy również zostały opisane. Metody są po prostu obiektami funkcji tworzonymi przez instrukcję def, zagnież- dżoną w treści instrukcji class. Patrząc na to abstrakcyjnie, metody określają zachowania egzem- plarzy obiektów, które mają być dziedziczone. Z punktu widzenia programisty należy rozumieć to tak, że metody działają dokładnie w taki sam sposób, jak proste funkcje, ale z jednym ważnym wyjątkiem: ich pierwszy argument zawsze otrzymuje egzemplarz obiektu, który jest wynikowym przedmiotem wywołania metody. Innymi słowy, język Python automatycznie odwzorowuje wywołania metod egzemplarza na funkcje metody danej klasy: egzemplarz.metoda(args...) = staje się = klasa.metoda(egzemplarz, args...) 2 Osoby znające język C++ mogą to potraktować jako coś zblilżonego do oznaczenia static dla danych klasy, czyli elementów (członków), które są przechowylwane w klasie niezależnie od egzemplarzy. W języku Python nie jest to niczym specjalnym: wszystkie atrybuty klasy są po prostu nazwami przypisanymi w instrukcji class bez względu na to, czy odwołują się do funkcji (metody języka C++), czy do czegoś innego (członkowie języka C++). /.-/2/46/79;+2/.6/;46/786/22+;  Klasa jest tu określana za pomocą procedury wyszukiwania, użytej w procesie dziedziczenia języka Python. Pierwszy argument specjalny w metodzie klasy bywa zazwyczaj nazywany zgodnie z konwen- cją self. Jest on podobny do wskaźnika this języka C++, lecz metody języka Python zawsze muszą kwalifikować argument self jawnie, aby można było pobrać lub zmienić atrybuty egzem- plarza, który jest przetwarzany przez bieżące wywołeanie metody. 6o+. Powrócimy teraz do przykładu i zdefiniujemy następuejącą klasę: class NextClass: # definiowanie klawsy def printer(self, text): # definiowanie mewtody print text Nazwa printer odnosi się do obiektu funkcji. Jest ona przypisana w zakresie instrukcji class, zatem staje się atrybutem klasy i jest dziedziczona przez każdy egzemplarz utworzony z tej klasy. Funkcja printer może być wywołana na dwa sposoby: przez egzemplarz leub przez samą klasę: x = NextClass() # tworzenie egzemplarza x.printer( Hello world! ) # wywołanie jego metody Hello world! Po wywołaniu za pomocą kwalifikacji egzemplarza (jak powyżej), argument self metody printer ma automatycznie przypisany egzemplarz obiektu (x), zaś argument text otrzymuje łańcuch przekazany przy wywołaniu ( Hello world! ). Wewnątrz metody printer argument self może mieć dostęp lub ustawić dane egzemplarza, ponieważ odwołuje się on do egzemplarza aktu- alnie przetwarzanego. Można także wywołać printer, przechodząc przez klasę za pomocą jaw- nego przekazania egzemplarza do argumentu self: NextClass.printer(x, Hello world! ) # metoda klasy Hello world! Wywołania skierowane przez egzemplarz i klasę mają dokładnie taki sam skutek, pod warunkiem, że przy przejściu poprzez klasę przekazywany jest ten sam egzemplarz obiektu. Za chwilę pokażemy, że wywołania przez klasę są podstawą rozszerzania (zamiaest zastępowania) dziedziczonych zachowań. Cały sens instrukcji class, działającej na przestrzeni nazw, polega na obsłudze dziedziczenia tych nazw. W języku Python dziedziczenie zachodzi wtedy, gdy obiekt jest kwalifikowany. Polega ono na przeszukiwaniu drzewa definicji atrybutu (jednej lub wielu przestrzeni nazw). Za każdym razem, gdy używa się wyrażenia o postaci obiekt.atrybut, w którym obiekt jest egzem- plarzem lub obiektem klasy, Python przeszukuje drzewo przestrzeni nazw na poziomie, na którym znajduje się obiekt, i wyżej. Szukany jest atrybut (jego pierwsze wystąpienie). Ponieważ defi- nicje znajdujące się na niższych poziomach w drzewie zastępują definicje z wyższych poziomów, dziedziczenie stwarza podstawy do specjalizacji.  3.+o +7 9.3;+.6/;++86,98(cid:20); Na rysunku 6.4 pokazano sposób, w jaki zbudowane są drezewa przestrzeni nazw. Ogólnie mówiąc: Rysunek 6.4. Budowa drzewa przestrzeni nazw i dziedz.iczenie  Atrybuty egzemplarzy są generowane za pomocą przypisań do atrybutów self w metodach.  Atrybuty klasy są tworzone za pomocą instrukcji (przypisań) w instruekcjach class.  Dowiązania klas nadrzędnych są tworzone za pomocą wpisania klas w nawiasach w nagłówku instrukcji class. Ogólnym wynikiem tych działań jest drzewo przestrzeni nazw atrybutów, które u podstawy ma egzemplarz, potem przechodzi do klasy, z której został wygenerowany ten egzemplarz, a następnie rozrasta się na wszystkie klasy nadrzędne podane w nagłówku tej klasy. Python przeszukuje to drzewo w kierunku do góry, rozpoczynając od poziomu egzemplarza. Przeszukiwanie odbywa się zawsze, gdy do pobrania nazwy atrybutu z egzemplarzae obiektu używana jest kwalifikacja3. #4/-++-+/83../.-32- Opisany wyżej model dziedziczenia, którego podstawą jest przeszukiwanie drzewa, daje dobrą okazję do specjalizacji systemów. Nazwy w procesie dziedziczenia są szukane najpierw w klasach podrzędnych, a następnie w nadrzędnych, zatem klasy podrzędne mogą zastępować swoje domyślne zachowania, definiując ponownie atrybuty klas nadrzędnych. Można zatem budować całe systemy jako hierarchie klas, które są rozszerzane poprzez dodawania nowych zewnętrznych klas podrzęd- nych, a nie poprzez zmiany istniejących powiązań logiecznych. 3 Ten opis nie jest kompletny, ponieważ atrybuty egzempllarza i klasy mogą być tworzone także za pomocą przypisania do obiektów na zewnątrz instrukcji class. Jest to jednak rzadziej spotykane i czasem powoduje więcej błędów (zmiany nie są ograniczone do ilnstrukcji class). W języku Python wszystkie atrybuty są zawsze dostępne domyślnie; o prywatności powliemy później w tym rozdziale. /.-/2/46/79;+2/.6/;46/786/22+;  Idea przeciążania nazw dziedziczonych prowadzi do różnorodnych technik specjalizacyjnych. Klasy podrzędne mogą np. całkowicie zastępować nazwy dziedziczone, pod warunkiem, że dostarczają nazw oczekiwanych przez klasy nadrzędne. Mogą one również rozszerzać metody klas nadrzęd- nych za pomocą ponownych wywołań tych klas z zastąpionej metody. Pokazaliśmy już zamianę w działaniu, oto zatem przykład pokazujący działanie rozszerzeń: class Super: ... def method(self): ... print in Super.method ... class Sub(Super): ... def method(self): # zastąpienie metody ... print starting Sub.method # tu dodanie działań ... Super.method(self) # startuje działanie domyślne ... print ending Sub.method ... Bezpośrednie wywołanie metody klasy nadrzędnej jest w tym miejscu sednem sprawy. Klasa Sub zamienia funkcję method klasy Super na swoją własną wyspecjalizowaną wersję. W ramach tej zamiany Sub wywołuje ponownie wersję wyeksportowaną przez Super, aby uzyskać zachowanie domyślne. Innymi słowy, Sub.method po prostu raczej rozszerza zachowanie Super.method, a nie całkowicie je zamienia: x = Super() # tworzenie egzemplarza Super x.method() # uruchomienie Super.method in Super.method x = Sub() # tworzenie egzemplarza Sub x.method() # uruchamienie Sub.method, wywołującego Superw.method starting Sub.method in Super.method ending Sub.method Rozszerzanie jest zwykle stosowane razem z konstruktorami. Metoda o specjalnej nazwie __init__ jest nazwą dziedziczoną i jako jedyna jest znaleziona i uruchomiona, gdy tworzony jest egzemplarz. W celu uruchomienia konstruktorów klasy nadrzędnej, metoda __init__ klasy podrzędnej powinna wywołać metodę __init__ klasy nadrzędnej za pomocą kwalifikacji klas (np. Class.__init__ (self,...)). Rozszerzanie jest jedynym sposobem tworzenia interfejsu do klasy nadrzędnej. Poniżej pokazano klasy podrzędne, które ilustrują ten podstawowy scheemat:  Super definiuje funkcje method i delegate, z których ostatnia oczekuje na działania (action) w klasie podrzędnej.  Inheritor nie dostarcza żadnych nowych nazw, a więc pobiera ewszystko to, co jest zdefiniowane w Super.  Replacer zastępuje metodę (method) w Super swoją własną wersją metody.  Extender przystosowuje metodę (method) klasy Super, zastępując ją i ponownie wywołując w celu uruchomienia domyślnego zachowania.  Provider wprowadza metodę action, na którą oczekuje metoda delegate klasy Super.  3.+o +7 class Super: def method(self): print in Super.method # domyślne def delegate(self): self.action() # oczekiwane class Inheritor(Super): pass class Replacer(Super): def method(self): print in Replacer.method class Extender(Super): def method(self): print starting Extender.method Super.method(self) print ending Extender.method class Provider(Super): def action(self): print in Provider.action if __name__ == __main__ : for klasa in (Inheritor, Replacer, Extender): print \n + klasa.__name__ + ... klasa().method() print \nProvider... Provider().delegate() W tym miejscu warto zwrócić uwagę na kilka rzeczy: kod samotestujący na końcu tego przykładu tworzy egzemplarze trzech różnych klas. Ponieważ klasy są obiektami, można je wstawiać do krotki i tworzyć egzemplarze w sposób podstawowy (ten temat omówimy później). Klasy mają także specjalny atrybut __name__, jak moduły — jest to po prostu wstępnie ustawiony łańcuch, zawierający nazwę podaną w nagłówku klasy. Gdy wywołujemy metodę delegate poprzez egzem- plarz obiektu Provider, język Python znajduje metodę action w Provider za pomocą zwy- kłego przeszukania drzewa: wewnątrz metody delegate w klasie Super, self odwołuje się do egzemplarza Provider. python specialize.py Inheritor... in Super.method Replacer... in Replacer.method Extender... starting Extender.method in Super.method ending Extender.method Provider... in Provider.action 6/- +2/34/6+836’;;+7+-  Przeciążanie operatorów opisaliśmy pobieżnie na początku tego rozdziału; tutaj uzupełnimy in- formacje i pokażemy powszechnie stosowane i przydatne metody przeciążania. Oto lista kluczo- wych wniosków, dotyczących przeciążania:  Przeciążanie operatora pozwala klasom na przechwytyewanie działania normalnych operacji języka Python.  Klasy mogą przeciążać wszystkie operatory wyrażeń językea Python. Klasy mogą także przeciążać operacje na obiektach: drukeowanie, wywołania, kwalifikację itd.   Przeciążanie powoduje, że egzemplarze klas działają peodobnie, jak wbudowane typy.  Przeciążanie jest wprowadzane za pomocą dostarczeniae specjalnie nazwanych metod klasy. Oto prosty przykład działającego przeciążania. Jeśli w klasie zapewnimy specjalnie nazwane me- tody, to Python automatycznie wywoła je, gdy egzemplarze klasy pojawią się w odpowiednich operacjach. Na przykład pokazana niżej klasa Number dostarcza metodę przesłaniania konstruk- tora egzemplarza (__init__) oraz metodę przesłaniania operacji odejmowania (__sub__). Metody specjalne stanowią punkt zaczepienia, który pozwala utworzyć powiązanie z operacjami wbudowanymi: class Number: def __init__(self, start): # w Number(stwart) self.data = start def __sub__(self, other): # w egzemplawrz - other return Number(self.data - other) # wynik ww nowym egzemplarzu from number import Number # pobiera klasę z modułu X = Number(5) # wywołuje Number.__init__(X, 5w) Y = X - 2 # wywołuje Number.__sub_w_(X, 2) Y.data 3 3.78+;3;//83.46/- +2+34/6+836(cid:20); Prawie wszystko to, co można zrobić z obiektami wbudowanymi, takimi jak liczby całkowite i listy, ma swoje odpowiedniki w specjalnie nazwanych metodach, służących do przeciążania w klasach. W tabeli 6.1 podano najczęściej spotykane i użyteczne metody specjalne; jest ich znacznie więcej, ale w książce mamy na nie za mało miejsca. Pełnej listy dostępnych metod o specjalnych nazwach należy szukać w innych książkach na temat języka Python lub w podręczniku systemowym do biblioteki Pythona. Nazwy wszystkich metod przeciążających rozpoczynają się i kończą dwoma znakami podkreślenia (po to, aby odróżnić je od innyceh nazw definiowanych w klasach). 6o+. Pokażemy teraz kilka metod z tabeli 6.1 na przykładaech.  3.+o +7 Tabela 6.1. Wybór metod przeciążania operatora Metoda Przeciąża Wywołanie __init__ __del__ __add__ __or__ __repr__ __call__ __getattr__ __getitem__ __setitem__ Konstruktor Destruktor Operator + Operator | (bitowe or) Tworzenie obiektu: Class() Zwolnienie obiektu X + Y X | Y Drukowanie, przekształcenia print X, `X` Wywołania funkcji X() Kwalifikacja Indeksowanie X.niezdefiniowany X[klucz], w pętli for, w testach Przypisanie indeksowane X[klucz] = wartość __getslice__ Wycinanie X[dolny:górny] __len__ __cmp__ __radd__ Długość (rozmiar) Porównanie len(X), testy prawdziwości X == Y, X Y Prawostronny operator + Nieegzemplarz + X ))1/88/))46/7o+2+;778/3.;3o+2+2./73;+/ Metoda __getitem__ przesłania operacje indeksowania egzemplarza: gdy egzemplarz X poja- wia się w wyrażeniu indeksowym, takim jak np. X[i], Python wywołuje metodę __getitem__ odziedziczoną przez egzemplarz (jeśli taka istnieje), przekazując X do pierwszego argumentu, zaś indeks w nawiasach kwadratowych do drugiego argumentu. Na przykład poniższa klasa zwraca kwadraty wartości indeksu: class indexer: ... def __getitem__(self, index): ... return index ** 2 ... X = indexer() for i in range(5): ... print X[i], # X[i] wywołuje __getitem__(X, i) ... 0 1 4 9 16 Pokażemy teraz specjalną sztuczkę, która nie zawsze jest rozumiana przez początkujących, cho- ciaż bywa bardzo użyteczna: wprowadzając instrukcję for w rozdziale 3., wspomnieliśmy, że działa ona w sposób powtarzalny, indeksując sekwencję od zera do większych wartości indeksów aż do przekroczenia granic indeksu. Dlatego właśnie __getitem__ można wykorzystać do prze- ciążania iteracji i testów zawierania. Jest to działanie w myśl hasła „kup jeden, drugi dostaniesz za darmo”: dowolny obiekt wbudowany lub obiekt zdefiniowany przez użytkownika, który reaguje na indeksowanie, reaguje także automatycznie na iteerację i test zawierania: class stepper: ... def __getitem__(self, i): ... return self.data[i] ... X = stepper() # X jest obiektem kroczącym 6/- +2/34/6+836’;;+7+-  X.data = Mielonka for item in X: # pętle for wywołują __getitem__ ... print item, # dla pozycji indeksowych 0..N ... M i e l o n k a l in X # operator in także wywołuje w__getitem__ 1 ))1/8+886));-;89/2/./023;+2/3.;3o+2++8+6,989 Metoda __getattr__ przesłania kwalifikacje atrybutów. Mówiąc dokładniej, jest ona wywo- ływana z nazwą atrybutu, podaną jako łańcuch wszędzie tam, gdzie następuje próba kwalifikacji egzemplarza za pomocą niezdefiniowanej (nie istniejącej) nazwy atrybutu. Nie jest ona wywoły- wana, jeśli Python może znaleźć atrybut, używając swojej procedury przeszukiwania drzewa dzie- dziczenia. Z powodu takiego zachowania __getattr__ jest przydatne jako punkt zaczepienia w ogólnych odpowiedziach na żądania atrybutów. Na przykład: class empty: ... def __getattr__(self, attrname): ... if attrname == age : ... return 36 ... else: ... raise AttributeError, attrname ... X = empty() X.age 36 X.name Traceback (innermost last): File stdin , line 1, in ? File stdin , line 6, in __getattr__ AttributeError: name W powyższym przykładzie klasa empty i jej egzemplarz X nie mają swoich własnych prawdziwych atrybutów, zatem dostęp do X.age będzie kierowany do metody __getattr__. Do self jest przypisany egzemplarz (X), zaś do attrname — łańcuch będący nazwą niezdefiniowanego atry- butu ( age ). Taka definicja klasy powoduje, że age wygląda jak prawdziwy atrybut, bowiem zwracana jest wartość wyrażenia kwalifikacyjnego X.age (tutaj: 36). Sposób obsługi innych atrybutów nie jest znany, a więc wywoływana jest wbudowana obsługa wyjątku AttributeError. Dzięki temu Python jest poinformowany o tym, że dana nazwa rzeczy- wiście nie jest zdefiniowana i zapytanie o atrybut (X.name) generuje błąd. Metodę __getattr__ będziemy jeszcze omawiać przy okazji opisywania delegacji, zaś o wyjątkach powiemy więcej w rozdziale 7. ))6/46));6+-+6/46//28+-!o+q-9-3; Oto przykład działania konstruktora __init__ i metody __add__ przeciążającej operator +, który przy okazji pokazuje metodę __repr__, zwracającą łańcuchową reprezentację egzemplarzy. Do przekształcania przetwarzanego obiektu self.data na łańcuch stosowane są odwrotne apo- strofy. Jeśli obiekt jest zdefiniowany, to metoda __repr__ jest wywoływana automatycznie podczas drukowania obiektów klasy lub ich przeksztaełcania na łańcuchy.  3.+o +7 class adder: ... def __init__(self, value=0): ... self.data = value # inicjowanie danych ... def __add__(self, other): ... self.data = self.data + other # dodawanie other w miejscu ... def __repr__(self): ... return `self.data` # przekształcanie na łańcuch ... X = adder(1) # __init__ X + 2; X + 2 # __add__ X # __repr__ 5 Podaliśmy tyle przykładów przeciążania, ile zmieściło się w książce. Pozostałe metody działają podobnie do tych, które zostały tu pokazane. Wszystkie z nich służą po prostu jako punkty zacze- pienia przy przesłanianiu operacji na wbudowanych typach. Niektóre metody przeciążania nie mają jednoznacznie określonej listy argumentów lub zwracanej wartości. W dalszych częściach książki pokażemy jeszcze działanie kilku z nich, lecz pełnego przeglądu tego zagadnienia należy szukać w dokumentacji. Po opisie klas i egzemplarzy obiektów mamy już komplet informacji na temat przestrzeni nazw języka Python. Zamieszczamy zatem krótkie podsumowanie wszystkich reguł stosowanych przy rozpoznawa- niu nazw. Przede wszystkim należy pamiętać o tym, że nazwy kwalifikowane i nazwy niekwalifikowa- ne są traktowane odmiennie, zaś niektóre zakresy słueżą do inicjacji przestrzeni nazw obiektów:  Nazwy niekwalifikowane (X) korzystają z zakresów.  Nazwy kwalifikowane (obiekt.X) korzystają z przestrzeni nazw obiektów.  Zakresy inicjują przestrzenie nazw obiektów (w modułaech i w klasach). +;2/;+03;+2/713,+2/.33/28946467+2+ Nazwy niekwalifikowane są zgodne z regułami LGB omawianymei dla funkcji w rozdziale 4. Przypisanie: X = wartość Powoduje, że nazwa staje się nazwą lokalną: tworzy lueb zmienia nazwę X w bieżącym zakresie lokalnym, chyba że użyto deklaracji global. Odwołanie: X Poszukuje nazwy X w bieżącym zakresie lokalnym, następnie w bieżącym ezakresie globalnym, a potem w zakresie wbudowanym. +;;+03;+2/46/786/2/2+;3,/8(cid:20); Nazwy kwalifikowane odnoszą się do atrybutów specyficznych obiektów i podlegają regułom, które przedstawiliśmy podczas omawiania modułów. Dla egzemplarzy obiektów i obiektów klasy reguły odwołań są poszerzone w taki sposób, aby zawierały perocedurę przeszukiwania dziedziczenia: 34/86/19o.+46/786/22+;  Przypisanie: object.X = wartość Tworzy lub zmienia nazwę atrybutu X w przestrzeni nazw obiektu, który jest kwalifikowaeny. Odwołanie: object.X Poszukuje nazwy atrybutu X w obiekcie, a następnie we wszystkich dostępnych kelasach powyżej tego obiektu (ale nie w modułach). #o3;246/786/22+; W rozdziale 5. pokazaliśmy, że przestrzenie nazw modułu są w rzeczywistości słownikami prezen- towanymi za pomocą wbudowanego atrybutu __dict__. To samo dotyczy także obiektów klasy i egzemplarzy obiektów: kwalifikacja jest w rzeczywistości słownikiem indeksowanym wewnętrz- nie, zaś dziedziczenie atrybutów oznacza po prostu eprzeszukiwanie powiązanych słowników. Poniższy przykład pokazuje sposób rozrastania się słowników przestrzeni nazw po wprowadzeniu klas. Należy tu zwrócić uwagę na następujący fakt: jeżeli atrybut self zostanie przypisany w jednej z dwóch klas, to utworzy on (lub zmieni) atrybut w słowniku przestrzeni nazw egzemplarza, a nie klasy. Przestrzenie nazw egzemplarzy obiektów rejestrują dane specyficzne dla tych egzemplarzy; są one także powiązane z przestrzeniami nazw tych klas, które są przeszukiwane w wyniku dziedziczenia. Na przykład X.hello zostaje ostatecznie znalezione w słowniku przestrzeni nazw klasy super. class super: ... def hello(self): ... self.data1 = mielonka ... class sub(super): ... def howdy(self): ... self.data2 = jajka ... X = sub() # tworzy nową przestrzeń nazw (swłownik) X.__dict__ {} X.hello() # zmienia przestrzeń nazw egzemwplarza X.__dict__ { data1 : mielonka } X.howdy() # zmienia przestrzeń nazw egzemwplarza X.__dict__ { data2 : jajka , data1 : mielonka } super.__dict__ { hello : function hello at 88d9b0 , __doc__ : None} sub.__dict__ { __doc__ : None, howdy : function howdy at 88ea20 } X.data3 = tost X.__dict__ { data3 : tost , data2 : jajka , data1 : mielonka
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Python. Wprowadzenie
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: