Programowanie – Python
Wojciech Czyżycki
Politechnika Krakowska
Wydział Mechaniczny
9 stycznia 2014
1 / 212
Agenda I
1
Praca, gdzie użyto pythona
Zasoby
Python
Narzędzia
Instalowanie modułów w Pythonie
Wersje pythona
2
Język python - podstawy
Operatory, typy danych i składnia
Operatory wg hierarchii
Wybrane typy wbudowane
Typ logczny – Boolean
Listy
Słowniki
Krotki
Zbiory
2 / 212
Agenda II
Reguły składniowe
Reguły nazewnictwa
Konwencje nazewnictwa
Przypisanie
If
Pętle While i For
Inne instrukcje
Print
Def
Global
Importowanie pakietów
3
Modele klas
Właściwości klas w pythonie
Instrukcja class
Składniki klas
3 / 212
Agenda III
4
Atrybuty klas a atrybuty obiektów
Więcej o dziedziczeniu
Abstrakcja w pythonie
Polimorfizm w praktyce
Rozszerzanie klas
5
try – except
try – finally
raise
Wyjątki użytkownika
6
7
Więcej o krotkach, słownikach i listach
4 / 212
Agenda IV
Słownik (dictionary)
Lista (list)
Plik (file)
8
Dekoratory klas
Dekoratory funkcji wbudowanych
9
Klasy – deskryptory, zarządzanie atrybutami,
metody specjalne
Deskryptory
Metody __getattr__ i __getattribute__
Atrybuty specjalne klas
Inne ważne metody specjalne klas
10
Wzorce projektowe – realizacja w pythonie
Czym są wzorce projektowe
Dekorator (decorator)
5 / 212
Agenda V
Obserwator (observer)
Strategia (strategy)
Stan (state)
Singleton (singleton)
Metoda szablonowa (template)
Opakowanie (Adapter, Wrapper)
Fasada (Facade)
Pyłek, Waga Piórkowa (Flyweight)
Polecenie (Command)
Abstrakcyjna fabryka klas (Abstract class factory)
Kompozyt (Composition pattern)
6 / 212
Wykład 1
Wstęp do języka Python
W Pythonie można zrobić wszystko to, co w Perlu, a dodatkowo jeszcze po
skończeniu da się przeczytać gotowy kod. [5]
7 / 212
Czym jest Python?
Python
Python jest interpretowanym językiem programowania, obiektowym, wysokiego
poziomu. Został on stworzony na początku lat 90-tych w Centrum Matematyki i
Informatyki w Amsterdamie przez Guido van Rossuma jako następca języka
ABC.
Python jest oprogramowaniem otwartym typu
Open-Source i opartym na licencji Python Software
Foundation License, zarządzanym przez Python
Software Foundation [11]
Składnia tego języka wyróżnia się dużą
przejrzystością i pozbawiona jest zbytecznych
elementów.
Skąd pochodzi nazwa języka?
8 / 212
Charakterystyka języka Python
1
Język ogólnego przeznaczenia. Wykorzystywany jest w aplikacjach webowych
jak i desktopowych. Często również do pisania skryptów.
2
Jest w pełni obiektowy, dlatego proste typy danych, takie jak:
bool, float,
int, complex
również są obiektami.
3
Możliwe jest stosowanie różnych paradygmatów programowania:
proceduralnego, obiektowego i funkcyjnego.
4
Typowanie dynamiczne. Oznacza to iż wartości posiadają typ, nie zmienne,
jak ma to miejsce w takich językach jak Java, C++. Nie posiada też typów
statycznych, zamiast tablic dostępne są listy.
5
Dostępny jest bardzo rozbudowany zestaw bibliotek oraz platform
programistycznych (framework). Tworzone są przez programistów często
w języku niższego poziomu np. w C.
6
Biblioteki GUI. W przypadku aplikacje desktopowych, dostępny jest szereg
bibliotek z GUI np. wxPython, Tkinter, PyGTK czy PyQt.
7
W pełni przenośny, może działać pod wieloma systemami operacyjnymi oraz
platformami m.in. Windows, Linux/Unix, Mac OS X.
9 / 212
Zastosowanie języka Python
Python jest używany w wielu firmach takich jak: Google, Yahoo, Nokia, IBM,
Dropbox czy NASA. Jest, obok Javy, głównym językiem programowania
Google App Engine.
Dla programistów aplikacji webowych dostępnych jest wiele różnych CMSów
napisanych w Pythonie (django-cms, plone, Merengue, Skeletonz i inne).
10 / 212
Użyteczne zasoby [3] I
The Zen of Python – http://www.python.org/dev/peps/pep-0020/
Konwencje nazewnictwa – http://www.python.org/dev/peps/pep-0008/
Dokumentacja języka i biblioteki standardowej –
http://www.python.org/doc/
11 / 212
Praca, gdzie użyto pythona
Oferty międzynarodowe: http://www.python.org/community/jobs/
Oferty krajowe: http://pl.python.org/forum/index.php?board=9.0
Oprogramowanie napisane w Pythonie bądź ożywające Pythona
http://en.wikipedia.org/wiki/List_of_Python_software
12 / 212
Charakterystyka języka Python I
Program w pythonie można uruchomić w dwóch trybach wykonywania:
interaktywnym, który polega na wprowadzenie programu bezpośrednio do
interpretatora. Wadą takiego działania jest utrata programu natychmiast po
zamknięciu interpretatora.
wsadowym, polegającym na napisaniu programu w pliku z rozszerzeniem .py,
który można uruchomić przez interpreter. Tryb ten umożliwia tworzenie
modułów, dzięki którym poszczególne pliki mogą komunikować się ze sobą.
Możliwe jest również tworzenie modułów w trakcie działania programu i ich
dynamiczna podmiana.
Kod źródłowy napisany w języku Python najpierw kompilowany jest do
postaci pośredniej (byte-code), która następnie wykonywana jest przez
wirtualną maszynę Pythona (PVM).
Istnieją narzędzia tworzące pliki wykonywalne ze skryptów i byte-codu
pythona, w takiej technice wykonany jest desktopowy klient dropboksa) –
pyInstaller
,
py2exe
.
13 / 212
Charakterystyka języka Python II
Python ma tylko dwie pętle
for
oraz
while
. Nie ma dostępnej trzeciej pętli
znanej z innych języków jaką jest
do while
. Stosowane są dwa typy list: lista
(
list
) oraz krotki (
tuple
). Szeroko stosowane są również słowniki
(
dictionary
).
Brak jest instrukcji
switch
, zamiast niej jest używany rozbudowany
if ...
elif ... else
, a w bardziej złożonych sytuacjach istnieją inne możliwości
opisane w [1, 10].
Nie ma przekazywania argumentów funkcji przez referencję (zmienną).
Możliwe jest jednaj obejście tego ograniczenia (
ctypes
).
Składnia języka pozbawiona jest zbędnych elementów:
Struktura programu wykorzystuje wcięcia dla rozróżnienia bloków, zamiast
słów kluczowych czy nawiasów.
Na końcach instrukcji brak średników
;
.
Struktura składni składa się z wcięć określających bloki programu:
14 / 212
Charakterystyka języka Python III
Listing 1: Struktura funkcji w pythonie
1
def
funkcja
:
2
if
warunek:
3
return
1
4
else
:
5
return
0
15 / 212
Python
CPython
Stroną domową Pythona w standardowej implementacji opartej na języku C –
nazywanej CPython jest: http://www.python.org/. Na tejże stronie w
dziale Download dostępne są instalatory Pythona na różne platformy.
W przypadku platformy Windows 64bit (amd-win 64) warto szukać pakietów
również na stronie prowadzonej przez Christopha Gohlke’go z nieoficjalnymi
wersjami pakietów: http://www.lfd.uci.edu/~gohlke/pythonlibs.
Inne implementacje
IronPython (.Net)
Jython (Java)
CLPython (Common Lisp)
PyPy (Python)
16 / 212
IDE
Edytor IDLE
1
jest wieloplatformowym, podstawowym, prostym edytorem
kodu Pythona i jednocześnie konsolą do pracy interaktywnej. Istnieje
rozbudowana wersja tego edytora dostępna pod adresem:
http://idlex.sourceforge.net/features.html
Wraz z biblioteką
pywin32
instalowany jest również alternatywny edytor
kodu Pythona PythonWin przeznaczony jedynie na platformę MS Windows.
Edytor ten również pozwala na pracę interaktywną.
Poza wymienionymi wyżej aplikacjami istnieje wiele innych, użytecznych edytorów
i środowisk IDE dla Pythona. Aktualne zestawienie można znaleźć na stronie
http://wiki.python.org/moin/IntegratedDevelopmentEnvironments.
1
IDLE przyjmuje się, że IDLE jest niedokładnym rozwinięciem od IDE, ale wg [6], nazwa to
pochodzi od nazwiska członka grupy Monty Python – Erica Idle
17 / 212
IDE
Warte polecenia IDE oparte na pythonie:
Eric – rozbudowane środowisko z wbudowanym debuggerem i sprawdzaniem
kodu podczas pisania – http://eric-ide.python-projects.org/,
Spyder – Scientific PYthon Development EnviRonment – lżejsze niż Eric
środowisko z wbudowanymi narzędziami do obliczeń numerycznych
i wizualizacji wyników – http://pythonhosted.org/spyder/.
Eclipse + PyDev
NetBeans (od wersji 7)
18 / 212
Instalowanie modułów – easy install
Generalnie istnieją dwa podstawowe sposoby instalacji modułów Pythona.
Pierwszy to tradycyjny program instalacyjny lub pakiet w systemach Linux, drugi
to skrypt
easy_install
. W przypadku wersji 32-bitowych i dopracowanych
pakietów najlepiej jest używać skryptu
easy_install
.
easy_install pywin32
easy_install wxpython
easy_install libxml
...
W przypadku wersji 64-bitowych nie wszystkie moduły są poprawnie obsługiwane
przez easy_instal. Problem dotyczy zwłaszcza modułów wykorzystujących pliki dll
z MS Visual Studio. W takim przypadku najwygodniej jest skorzystać
z repozytorium Unofficial Windows Binaries for Python Extension Packages
dostępnym pod adresem http://www.lfd.uci.edu/~gohlke/pythonlibs/
19 / 212
Wersje pythona – podobieństwa i różnice
Na zajęciach używany będzie Python w wersji 2.7.x, 64-bit na pod systemem MS
Windows 7 64bit.
W miarę możliwości stosowane będą rozszerzenia z wersji 3.0.x (kodowanie
UTF-8, stringi unicode, nowa składnia instrukcji
print()
).
20 / 212
Pierwszy kod
Python nie narzuca konkretnej struktury kodu, nie ma w nim oznaczenia początku
i końca programu. Popularny przykład dla początkujących Hello World!!! ma
w Pythonie następującą postać:
Listing 2: Cały kod programu Hello world!!! w Pythonie
1
(
"Hello world!!!"
)
21 / 212
Zalecana literatura
Do niniejszych zajęć zalecana jest literatura wg wykazu:
Dokumentacja Pythona [3]
Szerszy opis Pythona, jego podstawowych bibliotek i technik programowania:
[6–9].
Zaawansowane programowanie obiektowe [2].
22 / 212
Operatory, typy danych i składnia
Wykład 2
Operatory, typy danych i składnia
Python is fast enough for our site and allows us to produce maintainable features
in record times, with a minimum of developers, said Cuong Do, Software
Architect, YouTube.com
23 / 212
Operatory, typy danych i składnia
Operatory wg hierarchii [3, 5] I
yield X
– Protokół funkcji generatora send().
lambda args: expr
– Operator tworzenia funkcji anonimowych.
X if Y else Z
– Operator trójargumentowy (wyrażenie X będzie obliczone
tylko wtedy, gdy Y ma wartość true).
X or Y
– Logiczna operacja OR: wyrażenie Y będzie obliczone tylko wtedy,
gdy X ma wartość false.
X and Y
– Logiczna operacja AND: wyrażenie Y będzie obliczone tylko
wtedy, gdy X ma wartość true.
not X
– Logiczna negacja.
X in Y
,
X not in Y
– Członkostwo: iteratory, zbiory.
X is Y
,
X is not Y
– Testy tożsamości obiektów.
X < Y
,
X <= Y
,
X > Y
,
X >= Y
– Porównywanie wielkości, ustawianie
podzbiorów i nadzbiorów.
X == Y
,
X != Y
– Operatory równości.
X | Y
– Bitowa operacja
OR
, unia zbiorów.
24 / 212
Operatory, typy danych i składnia
Operatory wg hierarchii [3, 5] II
X ˆ Y
– Bitowa operacja
XOR
, różnica symetryczna zbiorów.
X & Y
– Bitowa operacja
AND
, część wspólna zbiorów.
X << Y
,
X >> Y
– Przesunięcie X w lewo (prawo) o Y bitów.
X + Y
,
X – Y
– Dodawanie (konkatenacja), odejmowanie (różnica zbiorów).
X * Y
,
X % Y
,
X / Y
,
X // Y
– Mnożenie (powtarzanie), reszta z dzielenia
(formatowanie), dzielenie, dzielenie całkowite.
-X
,
+X
– Jednoargumentowa negacja, tożsamość.
˜X
– Bitowa negacja (inwersja).
X ** Y
– Potęgowanie.
X[i]
– Indeksowanie (sekwencje, mapowanie, inne).
X[i:j:k]
– Wycinanie (ang. slicing) — wszystkie granice opcjonalne.
X(...)
– Wywołanie (funkcji, metody, klasy, innego obiektu wykonywalnego).
X.attr
– Referencja atrybutu.
(...)
– Krotka, wyrażenie, wyrażenie generatora.
[...]
– Lista (lista składana).
{...}
– Słownik, zbiór (słownik składany).
25 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – liczby [3, 5] I
1234, −24, 0
– Liczby całkowite (nieograniczona precyzja)[1].
1.23
,
3.14e-10
,
4E210
,
4.0e+210
,
1.
,
.1
– Liczby zmiennoprzecinkowe
(zwykle implementowane jako typ double języka C w implementacji
CPython).
0o177
,
0x9ff
,
0b1111
– Literały liczb całkowitych ósemkowe, szesnastkowe i
dwójkowe.
3+4j
,
3.0+4.0j
,
3J
– Liczby zespolone.
decimal.Decimal('1.33')
,
fractions.Fraction(4, 3)
– Typy bazujące
na modułach: liczby dziesiętne, ułamki.
Tworzenie liczb na podstawie innych obiektów lub ciągów znaków z możliwością
podania podstawy konwersji:
int()
,
float()
,
complex()
.
1
Typy liczbowe obsługują wszystkie działania liczbowe. W wyrażeniach z
typami mieszanymi Python konwertuje operandy w górę, do najwyższego
typu. W tej hierarchii liczby całkowite (
integer
) znajdują się niżej od
zmiennoprzecinkowych, a te z kolei są niżej od liczb zespolonych.
26 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – liczby [3, 5] II
2
W wersjach Pythona 3.0 i 2.6 liczby całkowite i zmiennoprzecinkowe
udostępniają również szereg metod oraz innych atrybutów.
3
Do zaawansowanych operacji matematycznych konieczny jest użycie
dodatkowych modułów
math
lub
cmath
dla liczb zespolonych.
27 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – łańcuchy
znaków [3, 5] I
Łańcuchy znaków zapisuje się w postaci serii znaków ujętych w cudzysłów
(apostrofy). Opcjonalnie można je poprzedzić znakiem desygnatora.
"Python's"
,
'Python"s'
– Apostrofy i cudzysłowy można stosować
zamiennie. Wewnątrz apostrofów można umieszczać cudzysłowy i na odwrót
– wewnątrz cudzysłowów apostrofy – bez potrzeby poprzedzania ich znakiem
lewego ukośnika.
"""To jest blok wielowierszowy"""
– Bloki umieszczone w potrójnych
cudzysłowach (apostrofach) pozwalają na prezentowanie wielu wierszy tekstu
w jednym łańcuchu. Pomiędzy wierszami są wstawiane znaczniki końca
wiersza (\n).
'M\'c Donalds\n'
– Sekwencje specjalne poprzedzone lewym ukośnikiem są
zastępowane przez specjalne wartości bajtowe (np. ’\n’ to bajt o dziesiętnej
wartości 10).
"To" "będzie" "scalone"
– Sąsiednie stałe łańcuchowe są scalane. Jeśli
zostaną ujęte w nawiasy, to mogą obejmować wiele wierszy.
28 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – łańcuchy
znaków [3, 5] II
r'surowy\łańcuch znaków'
,
R'kolejny \przykład'
– Tzw. ”surowe”
łańcuchy znaków (ang. raw strings) — znaki lewego ukośnika występujące
wewnątrz ciągów są interpretowane literalnie (z wyjątkiem przypadków, kiedy
występują na końcu łańcucha). Mechanizm ten przydaje się do prezentowania
wyrażeń regularnych oraz ścieżek dostępu w systemie DOS, np.
r’c:\katalog1\plik’.
u'...'
– Literał łańcuchowy Unicode dostępny wyłącznie w Pythonie 2.X (w
Pythonie 3 kodowanie Unicode jest obsługiwane przez standardowe obiekty
str).
str()
,
bytes()
,
bytearray()
– Ciągi znaków tworzone na podstawie
obiektów. W Pythonie 3.0 dostępna jest opcja kodowania (dekodowania)
Unicode.
hex()
,
oct()
,
bin()
– Ciągi znaków zawierających tekstowe reprezentacje
liczb w formacie ósemkowym, szesnastkowym i dwójkowym.
29 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – łańcuchy
znaków [3, 5] III
Literały łańcuchowe mogą zawierać sekwencje specjalne reprezentujące bajty o
specjalnym znaczeniu.
Uwaga
W pythonie > 2.6 można włączyć obsługę stringów w stylu pythona 3.x (bez
u
na
początku) przez użycie na początku pliku deklaracji
from __future__ import unicode_literals
30 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – łańcuchy znaków
– formatowanie [3, 5]
Zarówno w Pythonie 2.6, jak i 3.0 standardowe łańcuchy znaków
str
obsługują
dwa różne rodzaje formatowania:
1
wyrażenie formatujące z wykorzystaniem operatora %:
fmt % (wartości)
,
2
nowy sposób — wywołanie metody o składni:
fmt.format(wartości)
.
Oba te rodzaje tworzą nowe ciągi znaków na podstawie kodów zastąpień. Kody te
mogą być specyficzne dla różnych typów.
Listing 3: Formatowanie łańcuchów znaków
1
>>>
'%s, %s, %.2f'
% (
42
,
'spam'
,
1
/
3.0
)
2
'42, spam, 0.33'
3
>>>
'{0}, {1}, {2:.2f}'
.format(
42
,
'spam'
,
1
/
3.0
)
4
'42, spam, 0.33'
Na zajęciach zalecane jest stosowanie nowej metody formatowania.
31 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – Boolean [3, 5]
Boolean
Logiczny typ danych o nazwie
bool
dostarcza dwóch predefiniowanych stałych
True
i
False
(typ
bool
jest dostępny od wersji 2.3).
W większości zastosowań stałe te można traktować tak, jakby były liczbami
całkowitymi odpowiednio 1 i 0 (np. wyrażenie
True
+ 3 ma wartość 4). Typ
bool
jest jednak podklasą typu
int
, a jego instancje wyświetlają się inaczej niż
instancje typu
int
(wartość
True
wyświetla się jako
True
, a nie
"1"
i można ją
wykorzystywać w roli wbudowanej nazwy w testach logicznych).
32 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – Listy [3, 5]
Listy
Mutowalne (modyfikowalne) tablice złożone z referencji do obiektów, do których
dostęp uzyskuje się za pośrednictwem pozycji (przesunięcia).
Listy zapisuje się w formie rozdzielanego przecinkami ciągu wartości ujętych w
nawiasy kwadratowe.
[]
– Pusta lista.
[0, 1, 2, 3]
– Lista czteroelementowa: indeksy 0..3.
alist = ['spam', [42, 3.1415], 1.23, ]
– Zagnieżdżone podlisty:
instrukcja
alist[1][0]
pobiera 42.
alist = list('spam')
– Tworzy listę złożoną z wszystkich elementów
dowolnego iteratora poprzez wywołanie funkcji konstruktora typu.
alist = [x**2 for x in range(9)]
– Tworzy listę poprzez pobranie
wyników wyrażenia podczas iteracji (lista składana).
33 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – Słowniki [3, 5]
Słowniki
Mutowalne tablice złożone z referencji do obiektów, do których dostęp uzyskuje
się za pośrednictwem klucza, a nie pozycji.
Słowniki zapisuje się w postaci ciągu par klucz:wartość wewnątrz nawiasów
klamrowych.
{}
– Pusty słownik.
{'spam':2,'jajka':3}
– Słownik dwuelem.: klucze ’spam’ i ’jajka’.
adict = { 'info': { 42: 1, type("): 2 }, 'spam': [] }
– Słowniki
zagnieżdżone: instrukcja
adict['info'][42]
pobiera
1
.
adict = dict(name='Bogdan', wiek=45, stanowisko=('kie',
'inf'))
– Słownik poprzez przekazanie argumentów kluczowych do
konstruktora typu.
adict = dict(zip('abc', [1, 2, 3]))
– Słownik poprzez przekazanie
listy krotek klucz-wartość do konstruktora typu. To samo co:
adict =
dict([['a', 1], ['b', 2], ['c', 3]])
adict = {c: ord(c) for c in 'spam'}
– Wyrażenie słownika składanego
(Python 3).
34 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – Krotki [3, 5]
Krotki
Niemutowalne tablice złożone z referencji do obiektów, do których dostęp
uzyskuje się za pośrednictwem pozycji (przesunięcia).
Krotki zapisuje się w formie rozdzielanego przecinkami ciągu wartości ujętych w
nawiasy okrągłe. Nawiasy można czasami pominąć (np. w nagłówkach pętli
for
oraz instrukcjach przypisania
=
).
()
– Pusta krotka.
(0,)
– Krotka jednoelementowa.
(0, 1, 2, 3)
– Krotka czteroelementowa.
0, 1, 2, 3
– Inna postać krotki czteroelementowej (taka sama jak w
poprzednim wierszu). Nie jest prawidłowa w wywołaniach funkcji.
atuple = ('spam', (42, 'jajka'))
– Krotki zagnieżdżone – instrukcja
atuple[1][1]
pobiera ciąg
'jajka'
.
atuple = tuple('spam')
– Tworzy krotkę złożoną ze wszystkich
elementów dowolnego iteratora poprzez wywołanie konstruktora typu.
35 / 212
Operatory, typy danych i składnia
Wybrane typy wbudowane – Zbiory [3, 5]
Zbiory
Mutowalne i nieuporządkowane kolekcje unikatowych i niemutowalnych obiektów.
Zbiory są nieuporządkowane, nie realizują odwzorowania wartości na klucze, ale
obsługują iteracje i funkcje.
W Pythonie 2.x i 3.x zbiory można tworzyć poprzez wywołanie wbudowanej funkcji
set()
z argumentem w postaci iteratora. Jego elementy staną się elementami
utworzonego zbioru. W 3.x można je również tworzyć za pomocą
{...}
oraz
wyrażenia zbiorów składanych.
set()
– Pusty zbiór.
aset = set('spam')
– Czteroelementowy zbiór – wartości ’s’, ’p’, ’a’, ’m’
(funkcja pozwala na przekazanie dowolnego iteratora).
aset = {'s', 'p', 'a', 'm'}
– Czteroelementowy zbiór, taki sam jak
poprzedni (Python 3).
aset = {ord(c) for c in 'spam'}
– Wyrażenie tworzenia zbioru
składanego (Python 3).
aset = frozenset(range(−5, 5))
– Zamrożony (niemutowalny) zbiór 10
liczb całkowitych
−5...4
.
36 / 212
Operatory, typy danych i składnia
Reguły składniowe [3, 5] I
Przepływ sterowania
Instrukcje uruchamiają się kolejno, jedna po drugiej, o ile nie zostaną użyte
instrukcje sterujące (
if
,
while
,
for
,
raise
, wywołania itp.).
Bloki
Blok wyróżnia się poprzez wcięcie wszystkich jego instrukcji o tę samą liczbę spacji
bądź tabulacji. Tabulacja liczy się jako wystarczająca liczba spacji do przesunięcia
kolumny o liczbę pozycji równą wielokrotności liczby 8. Jeśli bloki są prostymi
instrukcjami, mogą występować w tym samym wierszu, co nagłówek instrukcji.
37 / 212
Operatory, typy danych i składnia
Reguły składniowe [3, 5] II
Instrukcje
Instrukcja kończy się wraz z końcem wiersza, ale może być kontynuowana w
kolejnych wierszach w przypadku, kiedy fizyczny wiersz kończy się ukośnikiem (\),
niezamkniętym nawiasem okrągłym, kwadratowym bądź klamrowym albo
niezamkniętym łańcuchem znaków z potrójnym apostrofem (cudzysłowem). W
jednym wierszu może występować wiele prostych instrukcji w przypadku, kiedy
zostaną rozdzielone średnikiem (
;
).
Komentarze
Komentarze rozpoczynają się od znaku
#
(nie w przypadku, gdy znak ten
występuje w stałej łańcuchowej), a kończą wraz z końcem wiersza.
38 / 212
Operatory, typy danych i składnia
Reguły składniowe [3, 5] III
Ciągi dokumentacyjne
Jeśli funkcja, plik modułu bądź klasa rozpoczynają się literałem łańcuchowym, to
jest on zapisywany w atrybucie
__doc__
obiektu. Więcej informacji na temat
automatycznego wydobywania dokumentacji oraz narzędzi do jej wyświetlania
można znaleźć w opisie funkcji
help()
, modułu
pydoc
oraz skryptów,
w podręczniku Python Library Reference.
Białe spacje
Ogólnie rzecz biorąc, białe spacje mają znaczenie tylko z lewej strony kodu, w
miejscach, gdzie do grupowania bloków stosuje się wcięcia. W pozostałych
przypadkach puste wiersze i spacje są ignorowane, chyba że pełnią funkcję
separatorów znaczników lub występują wewnątrz stałych łańcuchowych.
39 / 212
Operatory, typy danych i składnia
Reguły nazewnictwa – Format nazwy [3, 5]
Struktura – Nazwy definiowane przez użytkowników mogą rozpoczynać się
od litery bądź znaku podkreślenia (
_
). Dalej może występować dowolna liczba
liter, cyfr bądź znaków podkreślenia.
Słowa zarezerwowane – Żadna z nazw definiowanych przez użytkownika nie
może być taka sama jak dowolne z zarezerwowanych słów Pythona.
Rozróżnianie wielkich i małych liter – W nazwach definiowanych przez
użytkowników oraz słowach zarezerwowanych wielkość liter zawsze ma
znaczenie:
SPAM
,
spam
i
Spam
są różnymi nazwami.
Nieużywane znaczniki – W konstrukcjach składniowych Pythona nie
wykorzystuje się znaków
$
i
?
, choć znaki te mogą pojawić się w stałych
łańcuchowych i komentarzach, a znak
$
ma specjalne znaczenie w
mechanizmie zastępowania wzorców.
Tworzenie – Nazwy definiowane przez użytkowników tworzy się poprzez
przypisanie, ale w momencie odwoływania się do nich muszą być zdefiniowane
(np. liczniki muszą być jawnie zainicjowane na wartość zero).
40 / 212
Operatory, typy danych i składnia
Konwencje nazewnictwa [3, 5] I
Nazwy rozpoczynające się i kończące dwoma znakami podkreślenia (na
przykład
__init__
) mają dla interpretera specjalne znaczenie, ale nie są
słowami zarezerwowanymi.
Nazwy rozpoczynające się od jednego znaku podkreślenia (np.
_X
), którym są
przypisywane wartości na najwyższym poziomie modułu, nie są kopiowane
przez importy
from...*
(warto także zapoznać się z listą
__all__
nazw
eksportów modułu). W innych kontekstach jest to nieformalna konwencja dla
nazw wewnętrznych.
Nazwy rozpoczynające się dwoma podkreśleniami (ale niezakończone taką
sekwencją) – np.
__X
– w obrębie instrukcji class są poprzedzone prefiksem w
postaci nazwy klasy, w której je zdefiniowano.
Nazwy będącej pojedynczym podkreśleniem (
_
) używa się w interpreterze
interaktywnym (wyłącznie) do zapisania wyników ostatniej operacji obliczenia
wartości.
41 / 212
Operatory, typy danych i składnia
Konwencje nazewnictwa [3, 5] II
Nazwy funkcji wbudowanych i wyjątków (np.
open
,
SyntaxError
) nie są
słowami zarezerwowanymi. Nazwy te żyją w ostatnio przeszukiwanym zasięgu
i mogą być przypisane powtórnie w celu ukrycia wbudowanego znaczenia
w bieżącym zasięgu (np.
open=myfunction
).
Nazwy klas zwykle zaczynają się od wielkiej litery (np.
MyClass
), a nazwy
modułów od małej litery (np.
mymodule
).
Pierwszy argument funkcji, która jest metodą klasy, zwykle ma nazwę
self
.
42 / 212
Instrukcja przypisania [3, 5]
Listing 4: Instrukcje przypisania
1
cel = wyrazenie
2
cel1 = cel2 = wyrazenie
3
cel1, cel2 = wyrazenie1, wyrazenie2
4
cel1 += wyrazenie
5
cel1,cel2,... = iterator-o-tej-samej-dlugosci
6
(cel1, cel2, ...) = iterator-o-tej-samej-dlugosci
7
[cel1, cel2, ...] = iterator-o-tej-samej-dlugosci
8
cel1, *cel2,... = iterator-o-odpowiedniej-dlugosci
43 / 212
Przypisanie z aktualizacją [3, 5]
Listing 5: Instrukcje przypisania z aktualizacją
1
X += Y
#X = X + Y dodawanie
2
X &= Y
#X = X & Y bitowe AND
3
X -= Y
#X = X - Y różnica
4
X |= Y
#X = X | Y bitowe OR
5
X *= Y
#X = X * Y mnożenie
6
X ^= Y
#X = X ^ Y bitowe XOR
7
X /= Y
#X = X / Y dzielenie (2.0 klasyczne, 3.0 dokładne)
8
X >>= Y
#X = X >> Y przesunięcie w prawo o Y bitów
9
X %= Y
#X = X % Y reszta z dzielenia
10
X <<= Y
#X = X << Y przesunięcie w lewo o Y bitów
11
X **= Y
#X = X**Y potęgowanie X do Y
12
X //= Y
#X = X//Y dzielenie całkowite
44 / 212
Przypisanie sekwencji [3, 5]
W Pythonie 2.x i 3.x dowolną sekwencję (bądź też inny iterator) złożone z
wartości można przypisać do dowolnej sekwencji nazw, pod warunkiem że ich
długości są takie same (w pythonie 2.x).
Listing 6: Instrukcje przypisania sekwencji
1
>>> a, b, c, d = [
1
,
2
,
3
,
4
]
2
>>> a, d
3
(
1
,
4
)
4
>>>
for
(a, b, c)
in
[[
1
,
2
,
3
], [
4
,
5
,
6
]]:
5
...
(a, b, c)
6
1 2 3
7
4 5 6
8
#dla Pythona 3.x możliwe jest również
9
>>> a, *b = [
1
,
2
,
3
,
4
]
10
>>> a, b
11
(
1
, [
2
,
3
,
4
])
12
>>> a, *b, c = [
1
,
2
,
3
,
4
]
13
>>> a, b, c
14
(
1
, [
2
,
3
],
4
)
15
>>> *a, b = [
1
,
2
,
3
,
4
]
16
>>> a, b
17
([
1
,
2
,
3
],
4
)
45 / 212
Instrukcja If [3, 5]
Instrukcja if
Instrukcja
if
pozwala na wybór jednego lub kilku działań (bloków instrukcji) i
uruchamia grupę instrukcji powiązaną z pierwszym warunkiem
if
lub
elif
, który
jest prawdziwy, albo wykonuje grupę
else
, jeśli wszystkie warunki
if
(
elif
) mają
wartość
false
.
Listing 7: Instrukcja if
1
if
warunek:
2
grupa
3
[
elif
warunek:
4
grupa]*
5
else
6
grupa]
46 / 212
Instrukcja While [3, 5]
Instrukcja while
Pętla
while
to instrukcja pętli ogólnego przeznaczenia, która wykonuje pierwszą
grupę instrukcji w czasie, gdy warunek na początku instrukcji jest prawdziwy.
Instrukcja uruchamia grupę
else
w przypadku, gdy nastąpi zakończenie działania
pętli bez wykonania instrukcji
break
.
Listing 8: Instrukcja while
1
while
test:
2
grupa
3
[
else
:
4
grupa]
47 / 212
Instrukcja For [3, 5]
Instrukcja for
Pętla for realizuje iterację po sekwencji (bądź innym iteratorze). Przypisuje
elementy iteratora
iterator
do zmiennej
cel
i w każdej iteracji wykonuje
pierwszą grupę instrukcji. Instrukcja for uruchamia grupę
else
w przypadku, gdy
nastąpi zakończenie działania pętli bez wykonania instrukcji
break
. Zmienną
cel
instrukcji
for
może być dowolny obiekt, który może się znaleźć po lewej stronie
instrukcji przypisania (np.
for (x, y) in tuplelist:
.
Listing 9: Instrukcja for
1
for
cel
in
iterator:
2
grupa
3
[
else
:
4
grupa]
48 / 212
Inne instrukcje [3, 5]
Instrukcja pass
pass
– instrukcja-wypełniacz, która nie wykonuje żadnych działań. Używa się jej
w przypadku, gdy jest to syntaktycznie konieczne. W Pythonie 3.x podobny efekt
można uzyskać za pomocą wielokropka
(...)
.
Instrukcja break
break
– powoduje natychmiastowe zakończenie najbliższej instrukcji pętli
while
lub
for
z pominięciem powiązanych z nimi grup
else
.
Instrukcja continue
continue
– powoduje natychmiastowe przejście na początek najbliższej instrukcji
pętli
while
lub
for
i wznowienie wykonywania grupy instrukcji w pętli.
49 / 212
Instrukcja Del [3, 5]
Instrukcja del
Instrukcja
del
usuwa nazwy, elementy, wycinki i atrybuty, a także powiązania.
Listing 10: Instrukcja del
1
del
nazwa
2
del
nazwa[i]
3
del
nazwa[i:j:k]
4
del
nazwa.atrybut
50 / 212
Instrukcja print [3, 5]
Listing 11: Instrukcja print
1
([wartosc [, wartosc]*]
2
[, sep=lancuch-znakow] [, end=lancuch-znakow] [,
file
=plik])
Każda wartość oznacza obiekt do wyświetlenia. To wywołanie konfiguruje się za
pomocą trzech argumentów, które mogą być wyłącznie argumentami kluczowymi:
sep
oznacza łańcuch znaków, który ma być umieszczony pomiędzy
wartościami (domyślnie spacja:
' '
).
end
oznacza łańcuch znaków do umieszczenia na końcu wyświetlanego tekstu
(domyślnie znak nowego wiersza: ’
\n
’).
file
to obiekt postaci pliku, do którego jest zapisywany tekst (domyślnie
standardowe wyjście:
sys.stdout
).
51 / 212
Instrukcja def [3, 5]
Listing 12: Instrukcja def
1
def
nazwa
([arg,... arg=wartosc,... *arg, **arg]):
2
grupa
Instrukcja
def
służy do tworzenia nowych funkcji. Jej działanie polega na
utworzeniu obiektu funkcji i przypisaniu do niego zmiennej nazwa. Każde
wywołanie do obiektu funkcji generuje nowy, lokalny zasięg, w którym
przypisywane nazwy domyślnie są lokalne dla wywołania (o ile nie zostaną
zadeklarowane jako globalne).
52 / 212
Instrukcja def c.d. [3, 5] I
Argumenty przekazuje się przez przypisanie. W nagłówku instrukcji
def
można je
definiować, wykorzystując dowolny z czterech formatów.
arg
– Dopasowywany według nazwy lub pozycji.
arg=wartość
– Wartość domyślna, jeśli argument arg nie zostanie
przekazany.
*arg
– Pobiera dodatkowe argumenty pozycyjne jako nową krotkę.
**arg
– Pobiera dodatkowe argumenty kluczowe jako nowy słownik.
*nazwa, arg[=wartość]
– Za gwiazdką (*) mogą wystąpić wyłącznie
argumenty kluczowe (Python 3.0).
*, arg[=wartość]
– Efekt taki sam jak w poprzednim wierszu.
53 / 212
Instrukcja def c.d. [3, 5] II
Listing 13: Instrukcja def – argumenty
1
>>>
def
f
(a, *b, c):
(a, b, c)
# c – obowiązkowy argument kluczowy
2
...
3
>>> f(
1
,
2
, c=
3
)
4
1
(
2
,)
3
5
>>>
def
f
(a, *, c=
None
):
(a, c)
# c – opcjonalny argument kluczowy
6
...
7
>>> f(
1
)
8
1
None
Instrukcja
return
powoduje zakończenie funkcji, w której ją wywołano, oraz
zwraca wyrażenie jako wynik wywołania tej funkcji. Jeśli pominięto argument
wyrażenie, domyślnie zwracana jest wartość
None
.
Listing 14: Instrukcja return
1
return
[wyrazenie]
Aby zwrócić wynik funkcji, złożony z wielu wartości, można wykorzystać krotkę
54 / 212
Instrukcja global [3, 5]
Instrukcja
global
jest deklaracją przestrzeni nazw — jeśli użyje się jej wewnątrz
klasy lub instrukcji definicji funkcji, to powoduje ona, że wszystkie wystąpienia
ciągu
nazwa
w wybranym kontekście będą traktowane jako referencje do zmiennej
globalnej (poziomu modułu) zmiennej
nazwa
— niezależnie od tego, czy do
zmiennej nazwa zostanie przypisana wartość, i niezależnie od tego, czy zmienna
nazwa
jest już zdefiniowana.
Listing 15: Instrukcja global
1
global
nazwa [, nazwa]*
55 / 212
Instrukcja import [3, 5]
Listing 16: Instrukcja import
1
import
modul
[, modul]*
2
import
[pakiet.]* modul [, [pakiet.]* modul]*
3
import
[pakiet.]* modul
as
nazwa
4
[, [pakiet.]*modul
as
nazwa]*
Instrukcja
import
daje dostęp do modułów — importuje moduł jako całość.
Z kolei moduły zawierają nazwy pobierane według kwalifikacji (np.
moduł.attubut
).
Przypisania na najwyższym poziomie pliku Pythona tworzą atrybuty obiektu
modułu.
Klauzula
as
powoduje przypisanie zmiennej nazwa do importowanego obiektu
modułu. Jest to przydatne gdyż dostarcza krótszych synonimów dla długich
nazw modułów.
Argument moduł oznacza nazwę modułu docelowego — zazwyczaj jest to
plik z kodem źródłowym w Pythonie lub moduł skompilowany. Moduł ten
musi się znaleźć w katalogu w obrębie ścieżki
.
56 / 212
Importowanie pakietów [3, 5]
Jeśli w instrukcji
import
zostaną użyte nazwy prefiksów pakiet, to oznaczają
one nazwy okalających katalogów, natomiast ścieżki modułów rozdzielane
kropkami odzwierciedlają hierarchie katalogów.
Instrukcja importu postaci
import dir1.dir2.mod
ładuje plik modułu
podaje się jako nazwę pliku bez rozszerzenia (.py lub inne rozszerzenia są
pomijane).
Ścieżka wyszukiwania importowanych modułów
sys.path
to lista katalogów
inicjowana na podstawie katalogu głównego programu, ustawienia
PYTHONPATH
, zawartości pliku
.pth
oraz wartości domyślnych
obowiązujących w środowisku Pythona.
57 / 212
Instrukcja from [3, 5] I
Listing 17: Instrukcja from
1
from
[
pakiet.
]*
modul
import
nazwa [, nazwa]*
2
from
[
pakiet.
]*
modul
import
*
3
from
[
pakiet.
]*
modul
import
nazwa
as
innanazwa
4
from
[
pakiet.
]*
modul
import
(nazwa1, nazwa2, ...)
Instrukcja
from
importuje nazwy zmiennych z modułu. Dzięki niej można
później używać tych nazw bez potrzeby kwalifikowania ich za pomocą nazwy
modułu.
Instrukcja w postaci
from mod import *
kopiuje wszystkie nazwy
przypisane na najwyższym poziomie modułu z wyjątkiem nazw zaczynających
się pojedynczym znakiem podkreślenia lub nazw, których nie wymieniono w
atrybucie opisującym listę łańcuchów znaków modułu
__all__
(jeśli go
zdefiniowano).
Klauzula
as
służy do tworzenia synonimów.
58 / 212
Instrukcja from [3, 5] II
Ścieżki importowania pakiet działają tak samo jak w instrukcji import (np.
from dir1.dir2.mod import X
), ale ścieżka do pakietu musi być
wymieniona tylko w samej instrukcji
from
.
Ze względu na nowe reguły zasięgu format z użyciem gwiazdki (
*
), w
przypadku gdy instrukcja jest zagnieżdżona wewnątrz funkcji bądź klasy,
generuje ostrzeżenia w wersji 2.2 (w Pythonie 3.0 – błędy)
Od Pythona 2.4, nazwy importowane z modułu można ująć w nawiasy. Dzięki
temu instrukcja importu może obejmować kilka wierszy i nie wymaga to
użycia lewych ukośników.
Od Pythona 3.0, instrukcja postaci
from module import *
jest
niedozwolona wewnątrz funkcji, ponieważ uniemożliwia sklasyfikowanie
zasięgów nazw w momencie definicji.
Instrukcja
from
jest również wykorzystywana w celu umożliwienia
wprowadzania do języka eksperymentalnych dodatków. Robi się to za
pomocą instrukcji
from __future__ import nazwawłasności
. Instrukcja
w takim formacie może się znaleźć wyłącznie na początku pliku modułu
59 / 212
Wykład 3
Klasy I
Python has been an important part of Google since the beginning, and remains so
as the system grows and evolves. Today dozens of Google engineers use Python,
and we’re looking for more people with skills in this language. said Peter Norvig,
director of search quality at Google, Inc.
60 / 212
OOP vs python I
Dziedziczenie – rozbudowana implementacja dziedziczenia wielobazowego.
Implementacja tego złożonego i często kłopotliwego modelu w pythonie
uważana jest za udaną.
Hermetyzacja – hermetyzacja w pythonie jest słaba, jest to zgodne z
filozofią pythona aby nie być nadmiernie restrykcyjnym dla użytkownika. Tym
niemniej istnieją mechanizmy pozwalające blokować dostęp do wybranych
elementów klas (
_X
,
__X
, struktura modułu)
Polimorfizm – polimorfizm leży w naturze pythona, funkcje, metody czy
klasy starają się dopasować do dostarczanych im danych. U podstaw języka
leży pojęcie duck-typing
2
Abstrakcja – w pythonie można tworzyć klasy i metody abstrakcyjne
i metaklasy. Abstrakcja służy głownie upraszaniu kodu co w pythonie jest
szeroko stosowane dzięki czytelnej składni czy polimorfizmowi
2
jeśli chodzi jak kaczka i kwacze jak kaczka, to musi być kaczką
61 / 212
Stary i nowy model klas[3, 5] I
W pythonie mamy dwa rodzaje klas:
1
klasy starego typu – old-style classes – python 1 i 2
2
klasy nowego typu – new-style classes – domyślnie python 3, opcjonalnie
python > 2.2
Klasy starego typu otrzymujemy w pythone < 3.0, gdy definiujemy klasy gołe,
nie dziedziczące po niczym, lub klasy dziedziczące po klasach starego typu.
Klasy nowego typu otrzymujemy, gdy definiujemy klasy dziedziczące bo
object
, bezpośrednio lub pośrednio. Jawna deklaracja wymagana jest w
pytonie > 2.2.
Od pythona 3.0 dostępne są tylko klasy nowego typu
W przypadku klas starego i nowego typu, nieco inaczej zachowuje się funkcja
super()
. Przy rekurencyjnych wywołaniach metody nadrzędnej, w klasach
nowego typu przechodzimy wszystkich rodziców w pewnym porządku (tzw.
diament). W klasach starego typu możemy jednego rodzica odwiedzić więcej
niż raz.
62 / 212
Stary i nowy model klas[3, 5] II
W klasach nowego typu możemy definiować tzw. deskryptory (dekoratory).
Pozwalają one na definiowanie specjalnego typu atrybutów. Dostęp do
atrybutów zdefiniowanych przez deskryptory do których dostęp wygląda tak
samo jak dostęp do zwykłych statycznych pól, ale faktycznie powoduje
wywołanie metody na deskryptorze.
Korzystając z pythona < 3.0, aby zachować kompatybilność z wersją 3.0
należy zawsze jawnie dziedziczyć po
object
.
Dziedziczenie po
object
nie daje istotnych korzyści poza kompatybilnością z
nowymi rozwiązaniami gdyż klasa
object
nie definiuje żadnych pól, a jedynie
kilka metod typu
__str__
, do których rzadko się odwołujemy z klas
potomnych.
63 / 212
Właściwości klas w pythonie[3, 5] I
W pythonie wszystko jest obiektem.
Instrukcja
class
nie jest deklaracją jak np. w C++ ale pełnoprawnym
kodem, który tworzy obiekt klasy.
Klasy są atrybutami w modułach, czyli moduł jest traktowany również jako
klasa, jest to istotne o tyle, że w pythonie zawsze kod jest w module – każdy
plik .py jest modułem.
Funkcje będące metodami otrzymują specjalny pierwszy argument, zwykle o
nazwie
self
, który oznacza obiekt egzemplarza będący domniemanym
podmiotem wywoływanych metod. Argument ten daje dostęp do stanu
egzemplarza oraz jego atrybutów.
Definicje metod o specjalnych nazwach postaci
__X__
przechwytują działania
wbudowane.
Instrukcje przypisania wewnątrz grupy generują atrybuty klas dziedziczone
przez egzemplarze — zagnieżdżone instrukcje
def
tworzą metody, natomiast
instrukcje przypisania tworzą proste składowe klasy itp.
64 / 212
Instrukcja class I
Instrukcja
class
jest instrukcją złożoną, z ciałem wciętych instrukcji, które
zazwyczaj pojawia się pod nagłówkiem.
W nagłówku po nazwie klasy w nawiasach wymienione są klasy nadrzędne,
rozdzielone przecinkami. Podanie większej liczby klas nadrzędnych prowadzi
do dziedziczenia wielokrotnego. Nowy obiekt klasy dziedziczy z każdej z
wymienionych klas nadrzędnych w podanym porządku i jest przypisywany do
zmiennej nazwa.
Instrukcja
class
wprowadza nowy lokalny zasięg nazw. Wszystkie nazwy
przypisane wewnątrz instrukcji
class
generują atrybuty obiektu klasy
współdzielone przez wszystkie egzemplarze tej klasy.
Listing 18: Instrukcja class
1
class
<
nazwa
>(klasa_nadrz
ę
dna, ...):
# Przypisanie do nazwy
2
data = value
# Współdzielone dane klasy
3
def
method
(
self
, ...):
# Metody
4
self
.member = value
# Dane instancji
65 / 212
Składniki klas – atrybuty[3, 5] I
Wywołanie klasy generuje obiekty egzemplarzy (instancje). Każdy obiekt
egzemplarza może mieć własne atrybuty, a przy tym dziedziczy atrybuty klasy
oraz jej wszystkich klas nadrzędnych.
Zmiany wartości atrybutów klasy (w C++ zwanych statycznymi) wpływają
na wartości instancji, zmiany tych atrybutów w instancjach są ograniczone do
instancji.
66 / 212
Składniki klas – atrybuty[3, 5] II
Listing 19: Wspólne atrybuty klas
1
>>>
class
SharedData
:
2
...
spam =
42
# Wygenerowanie atrybutu danych klasy
3
...
4
>>> x = SharedData()
# Utworzenie dwóch instancji
5
>>> y = SharedData()
6
>>> x.spam, y.spam
# Dziedziczą i współdzielą zmienną spam
7
(
42
,
42
)
8
>>> SharedData.spam =
99
# Zmiana w klasie bazowej
9
>>> x.spam, y.spam, SharedData.spam
10
(
99
,
99
,
99
)
11
>>> x.spam =
88
12
>>> x.spam, y.spam, SharedData.spam
#Zmiana w instancji
13
(
88
,
99
,
99
)
67 / 212
Składniki klas – atrybuty[3, 5] III
Listing 20: Atrybuty klas i instancji
1
class
MixedNames
:
# Zdefiniowanie klasy
2
data =
'mielonka'
# Przypisanie atrybutu klasy
3
def
__init__
(
self
, value):
# Przypisanie nazwy metody
4
self
.data = value
# Przypisanie atrybutu instancji
5
def
display
(
self
):
6
(
self
.data, MixedNames.data)
#Atrybut instancji, atr. klasy
Listing 21: Atrybuty klas i instancji – interakcja
1
>>> x = MixedNames(
1
)
# Utworzenie dwóch obiektów instancji
2
>>> y = MixedNames(
2
)
# Każdy ma własne dane
3
>>> x.display(); y.display()
4
# self.data jest inny, Subclass.data jest tym samym
5
1
mielonka
6
2
mielonka
68 / 212
Składniki klas – Metody[3, 5, 12] I
Metody to po prostu obiekty funkcji utworzone za pomocą instrukcji
def
zagnieżdżonych w ciele instrukcji
class
.
Z abstrakcyjnego punktu widzenia metody udostępniają zachowanie, które
dziedziczą instancje klasy.
Z punktu widzenia programowania metody działają dokładnie tak samo jak
proste funkcje, z jednym kluczowym wyjątkiem — pierwszy argument metody
zawsze otrzymuje obiekt instancji, który jest domniemanym podmiotem
wywołania metody.
Obecnie python automatycznie odwzorowuje wywołania metod instancji na
funkcje metod klas. Czyli:
instancja.metoda(argumenty...)
jest tym
samym co:
klasa.metoda(instancja, argumenty...)
W metodzie klasy pierwszy argument jest najczęściej, zgodnie z konwencją,
nazywany
self
. Argument ten udostępnia metodom punkt zaczepienia z
powrotem do instancji będącej podmiotem wywołania.
Klasy generują wiele obiektów instancji, muszą więc stosować ten argument w
celu zarządzania danymi różniącymi się między poszczególnymi instancjami.
69 / 212
Składniki klas – Metody[3, 5, 12] II
Listing 22: Metody – przykład
1
class
NextClass
:
# Zdefiniowanie klasy
2
def
printer
(
self
, text):
# Zdefiniowanie metody
3
self
.message = text
# Modyfikacja instancji
4
(
self
.message)
# Dostęp do instancji
Listing 23: Metody – przykład – interakcja
1
>>> x = NextClass()
# Utworzenie instancji
2
>>>
# Wywołanie jej metody, wywołanie instancji
3
>>> x.printer(
'wywołanie instancji'
)
4
>>> x.message
# Modyfikacja instancji
5
'wywołanie instancji'
70 / 212
Składniki klas – Metody[3, 5, 12] III
Listing 24: Metody – wywołania
1
>>>
# Bezpośrednie wywołanie klasy
2
>>> NextClass.printer(x,
'wywołanie klasy'
)
3
'wywołanie klasy'
4
>>> x.message
# Ponowne wywołanie instancji
5
'wywołanie klasy'
Listing 25: Metody – wywołania – błędnie
1
>>> NextClass.printer(
'złe wywołanie'
)
2
TypeError: unbound method printer() must be
3
called
with
NextClass instance...
71 / 212
Składniki klas – Metody – Konstruktory i
destruktory[3, 5, 12] I
Klasy pythona nie mają jawnych konstruktorów
3
ani destruktorów
Metoda
__init__
jedynie przypomina działanie konstruktora, ustawia
początkowy stan instancji ale jej nie tworzy.
Metodę specjalną
__init__
nazywa się czasem pseudokonstruktorem lub,
bardziej właściwie, incjatorem
Wymuszone zwalnianie zasobów przy niszczeniu obiektu można osiągnąć
stosując metodę
__del__
W metodzie
__init__
(pseudokonstruktorze) czasami zachodzi konieczność
wywołania metody
__init__
przodka, można tego dokonać na 2 sposoby:
1
przez jawne wywołanie przez użycie nazwy klasy przodka
przodek.__init__()
2
przez użycie funkcji
super()
3
istniej konstruktor
__new__
, którego jednak w używa się tylko w specjalnych przypadkach
72 / 212
Składniki klas – Metody specjalne– [3, 5] I
Metody o nazwach
__XXXX__
są nazywane metodami specjalnymi, należą do nich
między innymi metody ciągów dokumentujących, inicjator (pseudokonstruktor)
__init__
, czy metody do przeciążania operatorów,
73 / 212
Składniki klas – Właściwości[3, 5] I
Właściwość tworzona jest za pomocą przypisania wyniku wbudowanej funkcji
do atrybutu klasy:
attribute = property(fget, fset, fdel, doc)
Właściwości dostępne są w Pythonie od wersji 2.6 oraz 3.0, jednak w
wersjach z serii 2.x wymagają pochodzenia obiektów w nowym stylu, by
przypisania działały poprawnie. By wykonać powyższy kod w Pythonie 2.7,
należy dodać
object
jako klasę bazową (w wersji 3.0 można dodać klasę
nadrzędną, jednak jest to domyślne i nie jest wymagane).
Przedstawiona tu metoda jest jednym z czterech sposobów definiowania
właściwości:
1
wbudowaną funkcją
property(fget, fset, fdel, doc)
2
3
deskryptory (klasy definiujące metody
__get__
,
__set__
i
__delete__
,
4
przeciążenie metod
__getattr__
lub
__getattribute__
,
__setattr__
,
__delattr__
74 / 212
Składniki klas – Właściwości[3, 5] II
Listing 26: Właściwości
75 / 212
Składniki klas – Właściwości[3, 5] III
1
class
Person
(
object
):
2
def
__init__
(
self
, name):
3
self
._name = name
4
def
getName
(
self
):
5
(
'pobieranie...'
)
6
return
self
._name
7
def
setName
(
self
, value):
8
(
'modyfikacja...'
)
9
self
._name = value
10
def
delName
(
self
)
11
(
'usunięcie...'
)
12
del
self
._name
13
name =
property
(getName, setName, delName,
"Dokumentacja właśc. name"
)
14
bob = Person(
'Robert Zielony'
)
# bob ma zarządzany atrybut
15
(bob.name)
# Wykonuje getName
16
bob.name =
'Robert A. Zielony'
# Wykonuje setName
17
(bob.name)
18
del
bob.name
# Wykonuje delName
19
(
'-'
*
20
)
20
anna = Person(
'Anna Czerwona'
)
# Anna także dziedziczy właściwość
21
(anna.name)
22
(Person.name.__doc__)
# Lub help(Person.name)
76 / 212
Wykład 4
Klasy w Pythonie cz. 2.
Python plays a key role in our production pipeline. Without it a project the size of
Star Wars: Episode II would have been very difficult to pull off. From crowd
rendering to batch processing to compositing, Python binds all things together,
said Tommy Burnette, Senior Technical Director, Industrial Light & Magic.
77 / 212
Więcej o dziedziczeniu – przykłady
80 / 212
Abstrakcja w pythonie
81 / 212
Polimorfizm w praktyce
82 / 212
Rozszerzanie klas
dodawanie atrybutów
dziedziczenie
83 / 212
Wykład 4
Obsługa wyjątków i moduły
Python is everywhere at ILM. It’s used to extend the capabilities of our
applications, as well as providing the glue between them. Every CG image we
create has involved Python somewhere in the process, said Philip Peterson,
Principal Engineer, Research & Development, Industrial Light & Magic.
84 / 212
Błędy składni
Błędy składniowe, znane również jako błędy parsingu, są prawdopodobnie
najbardziej powszechnym rodzajem zażaleń, które otrzymuje się podczas nauki
Pythona [3]
Listing 27: Błędy składni
1
>>>
while
True
'Hello world'
2
File
"<stdin>"
, line
1
,
in
?
3
while
True
'Hello world'
4
^
5
SyntaxError: invalid syntax
85 / 212
Kiedy występują wyjątki
Listing 28: Przykłady wyjątków [3]
1
>>>
10
* (
1
/
0
)
2
Traceback (most recent call last):
3
File
"<stdin>"
, line
1
,
in
?
4
ZeroDivisionError: integer division
or
modulo by zero
5
>>>
4
+ spam*
3
6
Traceback (most recent call last):
7
File
"<stdin>"
, line
1
,
in
?
8
NameError: name
'spam'
is not
defined
9
>>>
'2'
+
2
10
Traceback (most recent call last):
11
File
"<stdin>"
, line
1
,
in
?
12
TypeError: cannot concatenate
'str'
and
'int'
objects
86 / 212
Przechwytywanie wyjątków – try – except I
W sytuacji kiedy spodziewany się wystąpienia wyjątku należy użyć instrukcji
try
- except - else
. instrukcja
else
jest opcjonalna. Przy
except
można podać
jeden lub wiele wyjątków, przy których kod po
except
ma być wykonany.
Instrukcja
except
może być podawana wielokrotnie po jednym
try
.
Listing 29: Instrukcja try - except [3]
1
try
:
2
#kod w którym może wystąpić wyjątek
3
except
:
#można podać na jakie wyjątki ma reagować
4
#kod do wykonania w przypadku wystąpienia wyjątku
5
else
:
6
#kod do wykonania kiedy nie wystąpi wyjątek
87 / 212
Przechwytywanie wyjątków – try – except II
Listing 30: Instrukcja try - except: określone wyjątki [3]
1
try
:
2
f =
open
(
'myfile.txt'
)
3
s = f.readline()
4
i =
int
(s.strip())
5
except
IOError
as
e:
6
(
"I/O error({0}): {1}"
.format(e.errno, e.strerror))
7
except
ValueError:
8
(
u"Nie można przekształcić danych na typ integer"
)
9
except
(RuntimeError, TypeError, NameError):
10
(
u"Wyjątek typu: RuntimeError, TypeError, NameError"
)
11
except
:
12
(
u"Niespodziewany wjątek:"
, sys.exc_info()[
0
])
13
else
:
14
(
u"Nie było wyjątku."
)
Na początku wykonywana jest klauzula try (czyli instrukcje pomiędzy
try
a
except
)
88 / 212
Przechwytywanie wyjątków – try – except III
Jeżeli nie pojawi się żaden wyjątek klauzula
except
jest pomijana.
Wykonanie instrukcji
try
uważa się za zakończone
Jeżeli podczas wykonywania klauzuli
try
pojawi się wyjątek, reszta
niewykonanych instrukcji jest pomijana. Następnie, w zależności od tego, czy
jego typ pasuje do typów wyjątków wymienionych w części
except
,
wykonywany jest kod następujący w tym bloku, a potem interpreter
przechodzi do wykonywania instrukcji umieszczonych po całym bloku
try...except
W przypadku pojawienia się wyjątku, który nie zostanie dopasowany do
żadnego z wyjątków wymienionych w klauzuli
except
, zostaje on przekazany
do do następnych, zewnętrznych instrukcji
try
. Jeżeli również tam nie
zostanie znaleziony odpowiadający mu blok
except
, wyjątek ten nie zostanie
wyłapany, stanie nieobsłużonym wyjątkiem
Słowo kluczowe
as
(>2.5) pozwala na zdefiniowanie aliasu (skróconej nazwy)
do podanej nazwy klasy wyjątku (w starszych wersjach alias podawało się po
,
)
89 / 212
Zwalnianie zasobów – try - finally
Listing 31: Blok zwalniania zasobów try - finally [3]
1
>>>
def
divide
(x, y):
2
...
try
:
3
...
result = x / y
4
...
except
ZeroDivisionError:
5
...
(
"division by zero!"
)
6
...
else
:
7
...
(
"result is"
, result)
8
...
finally
:
9
...
(
"executing finally clause"
)
Obecnie można w instrukcji
try - except
na końcu dodawać instrukcję
finally
. Można również stosować konstrukcję
try - finally
bez
except
90 / 212
Zgłaszanie wyjątków – raise
raise
służy do sztucznego generowania wyjątku przez programistę
Listing 32: Zglaszanie wyjątków
1
>>>
try
:
2
...
raise
KeyboardInterrupt
3
...
finally
:
4
...
'Goodbye, world!'
5
...
6
Goodbye, world
!
7
KeyboardInterrupt
91 / 212
Klasy wyjątków użytkownika I
Możliwe jest tworzenie swoich wyjątków poprzez przypisanie napisu do zmiennej
lub stworzenie nowej klasy wyjątku. Klasa wyjątku powinna dziedziczyć po klasie
Exception
bezpośrednio lub pośrednio.
92 / 212
Klasy wyjątków użytkownika II
Listing 33: Własne wyjątki [3]
1
>>>
class
MyError
(Exception):
2
...
def
__init__
(
self
, value):
3
...
self
.value = value
4
...
def
__str__
(
self
):
5
...
return
repr
(
self
.value)
6
...
7
>>>
try
:
8
...
raise
MyError(
2
*
2
)
9
...
except
MyError
as
e:
10
...
'My exception occurred, value:'
, e.value
11
...
12
My exception occurred, value:
4
13
>>>
raise
MyError(
'oops!'
)
14
Traceback (most recent call last):
15
File
"<stdin>"
, line
1
,
in
?
16
__main__.MyError:
'oops!'
Struktura klas wyjątków w aktualnym pythonie z serii 2.x dostępna jest na stronie:
http://docs.python.org/2/library/exceptions.html
93 / 212
Moduły w pythonie I
Moduły
Moduł to jednostka najwyższego poziomu organizacji programu, która
przechowuje kod programu oraz dane celem ich późniejszego użycia.
moduły zazwyczaj odpowiadają plikom kodu pythona .py
modułami mogą być też pliki z bytekodem .pyc, .pyo i rozszerzenia napisane
w językach C, C++, Java i C# (.Net)
w ogólności każdy plik uruchamiany lub ładowany przez
import -- from
jest modułem
moduły nie mają żadnej specjalnej składni, w szczególności nawet pusty plik
może być modułem, a także główny plik programu dla innych programach
może również być modułem
Moduły realizują zadania:
ponowne wykorzystanie kodu
dzielenie przestrzeni nazw systemu – grupowanie komponentów sytemu
implementowanie współdzielonych usług i danych
94 / 212
Moduły w pythonie II
Instrukcje i funkcje związane z modułami
import
– pozwala plikowi importującemu pobrać moduł jako całość
from
– pozwala klientom pobierać określone zmienne modułu
imp.reload
– umożliwia przeładowanie kodu modułu bez zatrzymywania
programu
95 / 212
Moduły w pythonie – przykład I
Program jest systemem modułów.
Zawiera jeden plik skryptu najwyższego
poziomu (uruchamiany w celu wykonania
programu) i większą liczbę plików modułów
(importowanych bibliotek narzędzi).
Skrypty oraz moduły są plikami tekstowymi
zawierającymi instrukcje Pythona, choć
instrukcje z modułów zazwyczaj po prostu
tworzą obiekty, które mają być użyte później.
Biblioteka standardowa Pythona udostępnia
zbiór gotowych modułów.
Rysunek:
Architektura programu
w Pythonie [5]
96 / 212
Moduły – Import I
Instrukcja
import
powoduje następującą sekwencję działań:
1
odnalezienie modułu
2
skompilowanie modułu do bytekodu (o ile jest to konieczne)
3
wykonanie kodu modułu w celu utworzenia definiowanych przez niego
obiektów
Możliwe jest wielokrotne importowanie danego modułu, ale rzeczywiste ładowanie
odbywa się tylko dla pierwszego importu. Jeśli moduł jest ponownie
importowany to jest on pobierany z pamięci. Lista załadowanych modułów
przechowywana jest w obiekcie
sys.modules
.
97 / 212
Moduły – Ścieżka poszukiwań I
Kolejność wyszukiwania modułów jest następująca:
1
katalog główny programu (lub bieżący interpretera)
2
katalogi ze zmiennej systemowej
PYTHONPATH
3
katalogi biblioteki standardowej
4
Zawartość plików .pth
98 / 212
Moduły – Wybór pliku modułu I
W instrukcji
import
pomijane jest rozszerzenie pliku (np. .py). Jest to celowy
zabieg gdyż pliki modułów mogą mieć różne rozszerzenia. Instrukcja w postaci:
import b
może załadować:
1
plik z kodem źródłowym o nazwie b.py
2
plik z kodem bajtowym nazwie b.pyc
3
katalog o nazwie b w przypadku importowania pakietów
4
Skompilowany moduł rozszerzenia, zazwyczaj napisany w językach C lub
C++ i dynamicznie dołączany w momencie importowania (np. b.so w Linux,
b.dll lub b.pyd dla Cygwin i Windows).
5
Skompilowany moduł wbudowany napisany w języku C i statycznie dołączony
do Pythona.
6
Komponent pliku ZIP rozpakowywany automatycznie po zaimportowaniu.
7
Obraz z pamięci w przypadku zamrożonych plików wykonywalnych.
8
Klasę języka Java w wersji Pythona o nazwie Jython.
9
Komponent .NET w wersji Pythona o nazwie IronPython.
99 / 212
Moduły – Wybór pliku modułu II
Konflikty:
w przypadku występowania modułów o tej samej nazwie w różnych
katalogach ładowany jest pierwszy znaleziony
w przypadku znalezienia takich plików w jednym katalogu (np. .py, .pyc,
.dll) ładowanie odbywa się zgodnie ze standardową kolejnością ładowania
(która jednak może się zmienić w przyszłości
powinno się unikać nadawania plikom z tego samego katalogu tych samych
nazw cele uniknięcia niejednoznaczności
Moduły z innych katalogów?
Jeżeli chcemy pobrać moduł z katalogu innego niż bieżący i nie leżący na ścieżce
poszukiwać to jest to możliwe używając składni pakietów. W skrócie polega ona
na użyciu niezależniej od systemu plików notacji
import dir.subdir.modul
100 / 212
Moduły – subtelna różnica między from i
import [5] I
Listing 34: Instrukcja import module
1
>>>
import
module1
# Pobranie modułu jako całości
2
>>> module1.printer(
'Witaj, świecie!'
)
#Zapis z kropką w celu otrzymania zmiennej
3
Witaj,
ś
wiecie
!
Listing 35: Instrukcja from module
1
>>>
from
module1
import
printer
# Skopiowanie jednej zmiennej
2
>>> printer(
'Witaj, świecie!'
)
# Nie ma konieczności użycia nazwy modułu
3
Witaj,
ś
wiecie
!
101 / 212
Moduły – subtelna różnica między from i
import [5] II
Listing 36: Instrukcja from module import * – Niebezpieczeństwo nadpisania
zmiennych!
1
>>>
from
module1
import
*
# Skopiowanie wszystkich zmiennych
2
>>> printer(
'Witaj, świecie!'
)
3
Witaj,
ś
wiecie
!
102 / 212
Więcej o krotkach, słownikach i listach
Wykład 5
Więcej o krotkach, słownikach
i listach
Python plays a key role in our production pipeline. Without it a project the size of
Star Wars: Episode II would have been very difficult to pull off. From crowd
rendering to batch processing to compositing, Python binds all things together,
said Tommy Burnette, Senior Technical Director, Industrial Light & Magic.
103 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) I
mojaKrotka = ('A', 'b', 1 , 2.1, [1, 2, 3])
Krotki
Krotki tworzą proste grupy obiektów. Działają dokładnie tak jak listy, jednak nie
mogą być modyfikowane w miejscu (są niezmienne) i zazwyczaj są zapisywane
jako seria elementów w zwykłych nawiasach, a nie w nawiasach prostokątnych.
Większość metod mają wspólne z listami, ale nie wszystkie z uwagi na
niezmienność składników.
Cechy szczególne [5]
Krotki są uporządkowanymi kolekcjami dowolnych obiektów
Dostęp do krotek odbywa się po wartości przesunięcia
Krotki należą do kategorii niezmiennych sekwencji
Krotki mają stałą długość, są heterogeniczne i można je dowolnie zagnieżdżać
Krotki są tablicami referencji do obiektów
Krotki są szybsze i mniej zasobożerne od list
104 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) II
Składniki krotek nie mogą być modyfikowane w krotce, np. składniki
słowników i list będących składnikami krotek są modyfikowalne (patrz
przykład 37)
105 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) III
Listing 37: Pułapki niezmienności krotek
1
>>> a =
1
; L = [
0
,
1
,
2
]
2
>>> T = (
0
, a, L)
#krotka złożona z liczby, zmiennej i listy
3
>>> T
4
(
0
,
1
, [
0
,
1
,
2
])
5
>>> T[
1
]=
0
#próba zmiany liczby -> wyjątek
6
Traceback (most recent call last):
7
File
"<stdin>"
, line
1
,
in
<module>
8
TypeError:
'tuple'
object
does
not
support item assignment
9
>>> a =
0
# zmiana zmiennej poza krotką
10
>>> T
11
(
0
,
1
, [
0
,
1
,
2
])
# zmiana zmiennej nie wpłynęła na stan krotki
12
>>> L[
1
]=
0
# zmiana elementu listy poza krotką
13
>>> T
14
(
0
,
1
, [
0
,
0
,
2
])
# zmiana wpłynęła na zawartość listy w krotce
15
>>> T[
2
][
2
]=
0
# odwołanie do listy przez krotkę
16
>>> T
17
(
0
,
1
, [
0
,
0
,
0
])
# wystąpiła zmiana w liście w krotce
18
>>> L += [
11
]
# dodanie elementu do listy
19
>>> L
20
[
0
,
0
,
0
,
11
]
# stan listy po dodaniu elementu
21
>>> T
22
(
0
,
1
, [
0
,
0
,
0
,
11
])
# stan krotki po powiększeniu listy -> zmiana
106 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) IV
Typowe operacje:
()
Pusta krotka
T = (0,)
Krotka jednoelementowa
T = (0, 'Ni', 1.2, 3)
Krotka czteroelementowa
T = 0, 'Ni', 1.2, 3
Krotka czteroelementowa (można bez nawiasów)
T = ('abc', ('def', 'ghi'))
Zagnieżdżone krotki
T = tuple('mielonka')
Krotka elementów w obiekcie, na którym da się
wykonywać iterację
T[i]
Indeks
T[i][j]
Indeks indeksu
T[i:j]
Wycinek (slice)
len(T)
Długość (liczba elementów)
T1 + T2
Łączenie (konkatenacja)
T1 * 3
Powtórzenia
107 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) V
for x in T: print(x)
Iteracja
'mielonka' in T
Przynależność
Listing 38: Po co przecinek w krotce jednoelementowej? [5]
1
>>> x = (
40
)
# Liczba całkowita
2
>>> x
3
40
4
>>> y = (
40
,)
# Krotka zawierająca liczbę całkowitą
5
>>> y
6
(
40
,)
108 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) VI
Listing 39: Łączenie, powtarzanie, indeksowanie [5]
1
>>> (
1
,
2
) + (
3
,
4
)
# Konkatenacja
2
(
1
,
2
,
3
,
4
)
3
>>> (
1
,
2
) *
4
# Powtórzenie
4
(
1
,
2
,
1
,
2
,
1
,
2
,
1
,
2
)
5
>>> T = (
1
,
2
,
3
,
4
)
# Indeksowanie, wycinek
6
>>> T[
0
], T[
1
:
3
]
7
(
1
, (
2
,
3
))
109 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) VII
Listing 40: Konwersje [5]
1
>>> T = (
'cc'
,
'aa'
,
'dd'
,
'bb'
)
2
>>> tmp =
list
(T)
# Sporządzenie listy z elementów krotki
3
>>> tmp.sort()
# Sortowanie listy
4
>>> tmp
5
[
'aa'
,
'bb'
,
'cc'
,
'dd'
]
6
>>> T =
tuple
(tmp)
# Sporządzenie krotki z elementów listy
7
>>> T
8
(
'aa'
,
'bb'
,
'cc'
,
'dd'
)
9
>>>
sorted
(T)
# Można także użyć funkcji wbudowanej sorted
10
[
'aa'
,
'bb'
,
'cc'
,
'dd'
]
110 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) VIII
Listing 41: Konwersja listą składaną [5]
1
>>> T = (
1
,
2
,
3
,
4
,
5
)
2
>>> L = [x +
20
for
x
in
T]
3
>>> L
4
[
21
,
22
,
23
,
24
,
25
]
Listing 42: Rozpakowywanie
1
>>> T1 = (
1.41
,
2.71
)
2
>>> x, y = T1
3
>>> x
4
1.41
5
>>> y
6
2.71
Listing 43: Zwracanie
wielu
wartości
z funkcji przy użyciu krotki
1
>>>
def
f1
(a, b):
2
return
(a, b)
3
>>> f1(
1
,
2.3
)
4
(
1
,
2.3
)
5
>>> x, y = f1(
1
,
2.3
)
6
>>> x
7
1
8
>>> y
9
2.3
111 / 212
Więcej o krotkach, słownikach i listach
Krotka (tuple) IX
Krotki a listy
Niezmienność krotek zapewnia pewien stopień integralności. Możemy być
pewni, że krotka nie zostanie zmodyfikowana przez inną referencję umieszczoną
gdzieś w programie; w przypadku list takiej gwarancji nie ma. Krotki pełnią zatem
rolę deklaracji stałych z innych języków programowania, choć w Pythonie
stałość powiązana jest z obiektami, a nie zmiennymi.
112 / 212
Więcej o krotkach, słownikach i listach
Krotka nazwana (named tuple)
Krotki nazwane
Krotki nazwane działają identycznie jak zwykłe krotki, z tą różnicą, że można
wywoływać ich składniki po nazwie zamiast po indeksie.
Listing 44: Krotka nazwana[2]
1
>>>
from
collections
import
namedtuple
2
>>> Stock = namedtuple(
"Stock"
,
"symbol current high low"
)
3
>>> stockG = Stock(
"GOOG"
,
613.3
, high=
625.8
, low=
610.5
)
4
>>> stockM = Stock(
"MSFT"
,
30.2
, high=
30.7
, low=
30.19
)
5
>>> stockG.high
6
625.8
7
>>> stockM.symbol
8
'MSFT'
9
>>> stockM[
0
]
10
'MSFT'
11
>>> stockM[
1
]
12
30.2
13
>>>
113 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) I
mojSlownik = {'a':1, 2:2, (1, 2):3, 'klucz':"do zamku" }
Słowniki
Słowniki są nieuporządkowanymi, zmiennymi kolekcjami obiektów różnych
typów. Podstawowa różnica w stosunku do list i krotek polega na tym, że
w słownikach elementy przechowywane są zgodnie z kluczem, a nie pozycją
przesunięcia. W podobny sposób odbywa się dostęp do nich – za pomocą klucza.
Cechy szczególne [5]
Dostęp do słowników odbywa się po kluczu, a nie wartości przesunięcia
Słowniki są nieuporządkowanymi kolekcjami dowolnych obiektów
Słowniki mają zmienną długość, są heterogeniczne i mogą być dowolnie
zagnieżdżane
Słowniki należą do kategorii zmiennych odwzorowań (można modyfikować w
miejscu)
Słowniki są tabelami referencji do obiektów (tablicami asocjacyjnymi)
114 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) II
Typowe operacje:
{}
Pusty słownik
{'mielonka':2, 'jajka':3}
Słownik dwuelementowy
D = {'jedzenie': {'szynka': 1, 'jajka': 2}}
Zagnieżdżanie
D = dict(name='Bob', age=40)
Alternatywne konstruowanie
D = dict(zip(keyslist, valslist))
Słowa kluczowe, zzipowane pary
D = dict.fromkeys(['a', 'b'])
listy kluczy
D['jajka']; D['jedzenie']['szynka']
Indeksowanie po kluczach
D.keys()
Lista kluczy (metoda)
D.values()
Lista wartości
D.items()
Lista par (klucz, wartość)
D.copy()
kopie
D.get(key, default)
Wartości domyślne
D.update(D2)
Łączenie słowników
115 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) III
D.pop(key)
Usuwanie
len(D)
Długość (liczba par klucz:wartość
D[key]
Dostęp do wartości po kluczu
del D[key]
Usuwanie elementu po kluczu
list(D.keys())
Widok słownika (3.0)
D = {x: x*2 for x in range(10)}
Słownik składany (3.0)
Mieszanie
Kolejność elementów w słowniku nie pokrywa się z kolejnością definiowania.
Wynika to z zastosowanych algorytmów zapewniających szybki dostęp do
elementów (hashing). Z tego powodu operacje zakładające stały porządek
elementów od lewej do prawej strony (na przykład wycinki czy konkatenacja) nie
mają zastosowania do słowników. Wartości można pobrać jedynie za pomocą
klucza, a nie pozycji
116 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) IV
Listing 45: Definiowanie słownika i dostęp do elementu [5]
1
>>> D = {
'mielonka'
:
2
,
'szynka'
:
1
,
'jajka'
:
3
}
# Utworzenie słownika
2
>>> D[
'mielonka'
]
# Pobranie wartości po kluczu
3
2
4
>>>D
# Kolejność zostaje pomieszana
5
{
'szynka'
:
1
,
'jajka'
:
3
,
'mielonka'
:
2
}
Listing 46: Liczba wpisów, sprawdzanie istnienia klucza, lista kluczy [5]
1
>>>
len
(D)
# Liczba wpisów w słowniku
2
3
3
>>>
'szynka'
in
D
# Alternatywne sprawdzanie istnienia klucza
4
True
5
>>>
list
(D.keys())
# Utworzenie nowej listy kluczy
6
[
'szynka'
,
'jajka'
,
'mielonka'
]
117 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) V
Listing 47: Modyfikacja słownika w miejscu [5]
1
>>> D
2
{
'jajka'
:
3
,
'szynka'
:
1
,
'mielonka'
:
2
}
3
>>> D[
'szynka'
] = [
'grillowanie'
,
'pieczenie'
,
4
'smażenie'
]
# Zmiana wpisu
5
>>> D
6
{
'jajka'
:
3
,
'szynka'
: [
'grillowanie'
,
'pieczenie'
,
'smażenie'
],
7
'mielonka'
:
2
}
8
>>>
del
D[
'jajka'
]
# Usunięcie wpisu
9
>>> D
10
{
'szynka'
: [
'grillowanie'
,
'pieczenie'
,
'smażenie'
],
'mielonka'
:
2
}
11
>>> D[
'lunch'
] =
'Bekon'
# Dodanie nowego wpisu
12
>>> D
13
{
'lunch'
:
'Bekon'
,
'szynka'
: [
'grillowanie'
,
'pieczenie'
,
'smażenie'
],
14
'mielonka'
:
2
}
118 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) VI
Listing 48: Lista wartości, par: klucz, wartość [5]
1
>>> D = {
'mielonka'
:
2
,
'szynka'
:
1
,
'jajka'
:
3
}
2
>>>
list
(D.values( ))
3
[
1
,
3
,
2
]
4
>>> (D.items( ))
5
[ (
'jajka'
,
3
), (
'szynka'
,
1
), (
'mielonka'
,
2
)]
Listing 49: Wartość domyślna dla brakujących kluczy [5]
1
>>> D.get(
'mielonka'
)
# Klucz istnieje
2
2
3
>>>
(D.get(
'tost'
))
# Brakujący klucz
4
None
5
>>> D.get(
'tost'
,
88
)
6
88
119 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) VII
Listing 50: Łączenie słowników [5]
1
>>> D
2
{
'jajka'
:
3
,
'szynka'
:
1
,
'mielonka'
:
2
}
3
>>> D2 = {
'tost'
:
4
,
'ciastko'
:
5
}
4
>>> D.update(D2)
5
>>> D
6
{
'tost'
:
4
,
'ciastko'
:
5
'jajka'
:
3
,
'szynka'
:
1
,
'mielonka'
:
2
, }
Listing 51: Usuwanie wpisów po nazwie klucza [5]
1
# Usunięcie wpisu ze słownika po jego kluczu
2
>>> D
3
{
'tost'
:
4
,
'ciastko'
:
5
},
'jajka'
:
3
,
'szynka'
:
1
,
'mielonka'
:
2
,
4
>>> D.pop(
'ciastko'
)
5
5
6
>>> D.pop(
'tost'
)
# Usunięcie i zwrócenie wartości klucza
7
4
8
>>> D
9
{
'jajka'
:
3
,
'szynka'
:
1
,
'mielonka'
:
2
}
120 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) VIII
Listing 52: Usuwanie wpisu ze słownika po pozycji na liście kluczy [5]
1
# Usunięcie elementu z listy po jego pozycji
2
>>> L = [
'aa'
,
'bb'
,
'cc'
,
'dd'
]
3
>>> L.pop( )
# Usunięcie i zwrócenie ostatniego elementu
4
'dd'
5
>>> L
6
[
'aa'
,
'bb'
,
'cc'
]
7
>>> L.pop(
1
)
# Usunięcie elementu z określonej pozycji
8
'bb'
9
>>> L
10
[
'aa'
,
'cc'
]
121 / 212
Więcej o krotkach, słownikach i listach
Słownik (dictionary) IX
Listing 53: Iteracja po słowniku [5]
1
>>> table = {
'Python'
:
'Guido van Rossum'
,
2
...
'Perl'
:
'Larry Wall'
,
3
...
'Tcl'
:
'John Ousterhout'
}
4
...
5
>>> language =
'Python'
6
>>> creator = table[language]
7
>>> creator
8
'Guido van Rossum'
9
>>>
for
lang
in
table:
# Równoznaczne: for lang in table.keys()
10
...
lang,
'\t'
, table[lang]
11
...
12
Tcl John Ousterhout
13
Python Guido van Rossum
14
Perl Larry Wall
122 / 212
Więcej o krotkach, słownikach i listach
Lista (list) I
mojaLista = [1, 2.1, 'abc', (0,), "Ala":"ma kota"]
Lista
Listy są najbardziej elastycznym typem obiektu uporządkowanej kolekcji. Listy są
obiektami zmiennymi (mutowalnymi) czyli można je modyfikować w miejscu.
Cechy szczególne [3, 5]
Listy są uporządkowanymi kolekcjami dowolnych obiektów
Listy mają zmienną długość, są niejednorodne i można je dowolnie
zagnieżdżać
Listy należą do zmiennych sekwencji
Listy są tablicami referencji do obiektów (przypominają tablice wskaźników)
Typowe operacje:
L = []
Pusta lista
L = [0, 1, 2, 3]
Cztery elementy — indeksy od 0 do 3
123 / 212
Więcej o krotkach, słownikach i listach
Lista (list) II
L = ['abc', ['def', 'ghi']]
Zagnieżdżone podlisty
L = list('mielonka')
Lista elementów obiektu iterowanego
L = list(range(-4, 4))
Lista kolejnych liczb całkowitych
L[i]
Indeks
L[i][j]
Indeks indeksu
L[i:j]
Wycinek (slice)
len(L)
Długość (liczba elementów listy)
L1 + L2
Konkatenacja (łączenie)
L * 3
Powtórzenie
for x in L: print(x)
Iteracja
3 in L
Przynależność
L.append(4)
Dodawanie do listy
L.extend([5, 6, 7])
Rozszerzenie listy o podane elementy
L.insert(I, X)
Wstawienie obiektu
X
na pozycji
I
124 / 212
Więcej o krotkach, słownikach i listach
Lista (list) III
L.index(1)
Pozycja elementu 1 (pierwszego elementu)
L.count(X)
Liczba wystąpień elementu
X
L.sort()
Sortowanie
L.reverse()
Odwracanie
del L[k]
Usunięcie elementu o indeksie
k
del L[i:j]
Usunięcie wycinka miedzy elementami
i
i
j
L.pop( )
Usunięcie ostatniego bądź wskazanego elementu
L.remove(2)
Usunięcie pierwszego elementu listy o wartości
2
L[i:j] = []
Usunięcie wycinka między elementami
i
i
j
przez przypisanie
pustej listy
L[i] = 1
Przypisanie przez indeks
L[i:j] = [4,5,6]
Przypisanie wycinka przez indeks
125 / 212
Więcej o krotkach, słownikach i listach
Lista (list) IV
Listing 54: Długość, łączenie, powielanie [5]
1
>>>
len
([
1
,
2
,
3
])
# Długość
2
3
3
>>> [
1
,
2
,
3
] + [
4
,
5
,
6
]
# Konkatenacja
4
[
1
,
2
,
3
,
4
,
5
,
6
]
5
>>> [
'Ni!'
] *
4
# Powtórzenie
6
[
'Ni!'
,
'Ni!'
,
'Ni!'
,
'Ni!'
]
Listing 55: Operator + [5]
1
>>>
str
([
1
,
2
]) +
"34"
# To samo co "[1, 2]" + "34"
2
'[1, 2]34'
3
>>> [
1
,
2
] +
list
(
"34"
)
# To samo co [1, 2] + ["3", "4"]
4
[
1
,
2
,
'3'
,
'4'
]
126 / 212
Więcej o krotkach, słownikach i listach
Lista (list) V
Listing 56: Przynależność i iteracja [5]
1
>>>
3
in
[
1
,
2
,
3
]
# Przynależność
2
True
3
>>>
for
x
in
[
1
,
2
,
3
]:
4
...
(x, end=
' '
)
# Iteracja
5
...
6
1 2 3
Listing 57: Lista składana, iterowanie stringów [5]
1
>>> res = [c *
4
for
c
in
'JAJKO'
]
# Lista składana
2
>>> res
3
[
'JJJJ'
,
'AAAA'
,
'JJJJ'
,
'KKKK'
,
'OOOO'
]
127 / 212
Więcej o krotkach, słownikach i listach
Lista (list) VI
Listing 58: Indeksowanie, wycinki [5]
1
>>> L = [
'mielonka'
,
'Mielonka'
,
'MIELONKA!'
]
2
>>> L[
2
]
# Wartości przesunięcia rozpoczynają się od 0
3
'MIELONKA!'
4
>>> L[-
2
]
# Wartość ujemna: odliczamy od końca
5
'Mielonka'
6
>>> L[
1
:]
# Wycinek pobiera części listy
7
[
'Mielonka'
,
'MIELONKA!'
]
128 / 212
Więcej o krotkach, słownikach i listach
Lista (list) VII
Listing 59: Macierze [5]
1
>>> matrix = [[
1
,
2
,
3
], [
4
,
5
,
6
], [
7
,
8
,
9
]]
2
>>> matrix[
1
]
3
[
4
,
5
,
6
]
4
>>> matrix[
1
][
1
]
5
5
6
>>> matrix[
2
][
0
]
7
7
8
>>> matrix = [[
1
,
2
,
3
],
9
... [
4
,
5
,
6
],
10
... [
7
,
8
,
9
]]
11
>>> matrix[
1
][
1
]
12
5
129 / 212
Więcej o krotkach, słownikach i listach
Lista (list) VIII
Listing 60: Wycinki i podstawianie [5]
1
>>> L = [
'mielonka'
,
'Mielonka'
,
'MIELONKA!'
]
2
>>> L[
1
] =
'jajka'
# Przypisanie do indeksu
3
>>> L
4
[
'mielonka'
,
'jajka'
,
'MIELONKA!'
]
5
>>> L[
0
:
2
] = [
'najsmaczniejsza'
,
'jest'
]
# Przypisanie do wycinka: usunięcie i wstawienie
6
>>> L
# Zastąpienie elementów 0 i 1
7
[
'najsmaczniejsza'
,
'jest'
,
'MIELONKA!'
]
Listing 61: Dodawanie elementów i sortowanie [5]
1
>>> L.append(
'puszkowana'
)
# Dodanie elementu na końcu listy
2
>>> L
3
[
'najsmaczniejsza'
,
'jest'
,
'MIELONKA!'
,
'puszkowana'
]
4
>>> L.sort( )
# Sortowanie listy ('M' < 'j')
5
>>> L
6
[
'MIELONKA!'
,
'jest'
,
'najsmaczniejsza'
,
'puszkowana'
]
130 / 212
Więcej o krotkach, słownikach i listach
Lista (list) IX
Listing 62: Sposoby sortowania [5]
1
>>> L = [
'abc'
,
'ABD'
,
'aBe'
]
2
>>> L.sort()
# Sortowanie bez uwzględnienia wielkości liter
3
>>> L
4
[
'ABD'
,
'aBe'
,
'abc'
]
5
>>> L = [
'abc'
,
'ABD'
,
'aBe'
]
6
>>> L.sort(key=
str
.lower)
# Normalizacja do małych liter
7
>>> L
8
[
'abc'
,
'ABD'
,
'aBe'
]
9
>>>
10
>>> L = [
'abc'
,
'ABD'
,
'aBe'
]
11
>>> L.sort(key=
str
.lower, reverse=
True
)
# Zmiana kolejności sortowania
12
>>> L
13
[
'aBe'
,
'ABD'
,
'abc'
]
131 / 212
Więcej o krotkach, słownikach i listach
Lista (list) X
Listing 63: Rozszerzanie, odwracanie, sortowanie [5]
1
>>> L = [
1
,
2
]
2
>>> L.extend([
3
,
4
,
5
])
# Dodanie kilku elementów
3
>>> L
4
[
1
,
2
,
3
,
4
,
5
]
5
>>> L.pop()
# Usunięcie i zwrócenie ostatniego elementu
6
5
7
>>> L
8
[
1
,
2
,
3
,
4
]
9
>>> L.reverse()
# Odwrócenie w miejscu
10
>>> L
11
[
4
,
3
,
2
,
1
]
12
>>>
list
(
reversed
(L))
# Wbudowana funkcja odwracająca sekwencję
13
[
1
,
2
,
3
,
4
]
132 / 212
Więcej o krotkach, słownikach i listach
Lista (list) XI
Listing 64: Usuwanie zwykłe i wycinkiem [5]
1
>>> L
2
[
'MIELONKA!'
,
'jest'
,
'najsmaczniejsza'
,
'puszkowana'
]
3
>>>
del
L[
0
]
# Usunięcie jednego elementu
4
>>> L
5
[
'jest'
,
'najsmaczniejsza'
,
'puszkowana'
]
6
>>>
del
L[
1
:]
# Usunięcie całej części
7
>>> L
# To samo co L[1:] = []
8
[
'jest'
]
133 / 212
Więcej o krotkach, słownikach i listach
Plik (file) I
Pliki
Pliki są nazwanymi obiektami przechowującymi dane, którymi zarządza system
operacyjny. W pythonie wbudowana funkcja
open
tworzy obiekt pliku, który
zawiera łącze do pliku. Po wywołaniu
open
można przenieść dane do pliku
zewnętrznego oraz czytać nie z niego wywołując metody obiektu pliku [5].
Typowe operacje:
output = open(r'C:\spam', 'w')
Utworzenie pliku do zapisu
input = open('data', 'r')
Utworzenie pliku do odczytu
input = open('data')
To samo co z
'r'
bo
'r'
jest trybem domyślnym
aString = input.read()
Wczytanie całego pliku do jednego łańcucha
znaków
aString = input.read(N)
Wczytanie kolejnych
N
bajtów do łańcucha
znaków
134 / 212
Więcej o krotkach, słownikach i listach
Plik (file) II
aString = input.readline()
Wczytanie następnego wiersza do do
łańcucha znaków wraz ze znakiem końca linii
aList = input.readlines()
Wczytanie całego pliku do listy łańcuchów
znaków z poszczególnymi wierszami
output.write(aString)
Zapisanie łańcucha bajtów do pliku
output.writelines(aList)
Zapisanie do pliku wszystkich łańcuchów
znaków z wierszami znajdujących się w liście
output.close()
Ręczne zamknięcie pliku. Nie jest obowiązkowe, gdyż plik
jest zwalniany gdy skończymy z nim pracę (lub program wyjdzie z zasięgu
zmiennej plikowej)
output.flush()
Opróżnienie bufora wyjściowego bez zamykania pliku
anyFile.seek(N)
Zmiana pozycji w pliku na wartość przesunięcia
N
dla
następnej operacji
for line in open('data'): print(line)
Iteracje pliku wiersz po wierszu
open('f.txt', encoding='latin-1')
Pliki tekstowe Unicode Pythona
3.0 (łańcuchy znaków
str
)
135 / 212
Więcej o krotkach, słownikach i listach
Plik (file) III
open('f.bin', 'rb')
Pliki bajtów binarnych Pythona 3.0 (łańcuchy
znaków
bytes
)
Parametry funkcji
open()
[3]:
open(name[, mode[, buffering]])
name
– nazwa pliku
mode
– tryb obsługi pliku:
'r'
– odczyt (domyślny)
'w'
– zapis
'a'
– dołączanie
'b'
– tryb binarny
'+'
– dołączone po literze daje możliwość zarówno odczytu jak i zapisu
buffering
– zarządza buforowaniem
-1
– domyślne buforowanie systemowe
0
– brak buforowania
1
– buforowanie jednej linii
<1
– przybliżona wielkość bufora w bajtach
136 / 212
Więcej o krotkach, słownikach i listach
Plik (file) IV
Uwaga
Operacje na plikach, a zwłaszcza tryby:
'b'
,
'a'
,
'+'
i buforowanie mogą się
nieco różnić na różnych SO.
Uwagi na temat używania plików:
Do wczytywania wierszy najlepiej nadają się iteratory plików
for line in myFile: print(line)
Zawartość pliku to łańcuchy znaków, a nie obiekty
Wywołanie
close()
jest zazwyczaj opcjonalne
Pliki są buforowane i można je przeszukiwać
137 / 212
Więcej o krotkach, słownikach i listach
Plik (file) V
Listing 65: Otwarcie, zapis, odczyt i zamknięcie pliku tekstowego [5]
1
>>> myfile =
open
(
'myfile.txt'
,
'w'
)
# Otwarcie do zapisu tekstowego (tworzy pusty plik)
2
>>> myfile.write(
'witaj, pliku tekstowy\n'
)
# Zapisanie wiersza tekstu
3
22
4
>>> myfile.write(
'żegnaj, pliku tekstowy\n'
)
5
23
6
>>> myfile.close()
# Zrzucenie bufora wyjściowego na dysk
7
>>> myfile =
open
(
'myfile.txt'
)
# Otwarcie do odczytu tekstu — 'r' jest domyślne
8
>>> myfile.readline()
# Wczytanie wierszy z powrotem
9
'witaj, pliku tekstowy\n'
10
>>> myfile.readline()
11
'żegnaj, pliku tekstowy\n'
12
>>> myfile.readline()
# Pusty łańcuch znaków — koniec pliku
13
''
138 / 212
Więcej o krotkach, słownikach i listach
Plik (file) VI
Listing 66: Obsługa znaku końca linii [5]
1
>>>
open
(
'myfile.txt'
).read()
# Wczytanie wszystkiego naraz do łańcucha znaków
2
'witaj, pliku tekstowy\nżegnaj, pliku tekstowy\n'
3
>>>
(
open
(
'myfile.txt'
).read())
# Sposób wyświetlania przyjazny dla użytkownika
4
witaj, pliku tekstowy
5
ż
egnaj, pliku tekstowy
6
###############################
7
>>>
for
line
in
open
(
'myfile'
):
# Użycie iteratorów plików, a nie wczytywania
8
...
(line, end=
''
)
9
...
10
witaj, pliku tekstowy
11
ż
egnaj, pliku tekstowy
139 / 212
Więcej o krotkach, słownikach i listach
Plik (file) VII
Listing 67: Obsługa plkiów binarnych [5]
1
>>> data =
open
(
'data.bin'
,
'rb'
).read()
# Otwarcie pliku binarnego: rb = "read binary"
2
>>> data
# Łańcuch bytes przechowuje dane binarne
3
b
'\x00\x00\x00\x07mielonka\x00\x08'
4
>>> data[
4
:
12
]
# Działa jak łańcuch znaków
5
b
'mielonka'
6
>>> data[
4
:
12
][
0
]
# Ale tak naprawdę to małe 8-bitowe liczby całkowite
7
109
8
>>>
bin
(data[
4
:
12
][
0
])
# Funkcja bin z Pythona 3.0
9
'0b1101101'
Przechowywanie obiektów pythona w plikach (serializacja) – moduł
pickle
140 / 212
Więcej o krotkach, słownikach i listach
Plik (file) VIII
Listing 68: Przechowywanie obiektów w plikach [5]
1
>>> D = {
'a'
:
1
,
'b'
:
2
}
2
>>> F =
open
(
'datafile.pkl'
,
'wb'
)
3
>>>
import
pickle
4
>>> pickle.dump(D, F)
# Serializacja dowolnego obiektu w pliku
5
>>> F.close()
6
################################
7
>>> F =
open
(
'datafile.pkl'
,
'rb'
)
8
>>> E = pickle.load(F)
# Załadowanie dowolnego obiektu z pliku
9
>>> E
10
{
'a'
:
1
,
'b'
:
2
}
141 / 212
Wykład 7
Dekoratory
Journyx technology, from the source code of our software to the code that
maintains our Web site and ASP sites, is entirely based on Python. It increases
our speed of development and keeps us several steps ahead of competitors while
remaining easy to read and use. It’s as high level of a language as you can have
without running into functionality problems. I estimate that Python makes our
coders 10 times more productive than Java programmers, and 100 times more
than C programmers. – Curt Finch, CEO, Journyx.
142 / 212
Dekoratory I
@property: def myPrint(self, x): print(x)
Dekoracja [5]
Dekoracja jest sposobem określania kodu zarządzającego dla funkcji oraz klas.
Dekoratory przybierają postać obiektów wywoływalnych (to znaczy funkcji), które
przetwarzają inne obiekty wywoływalne (
callable
).
W obecnie w pythonie występują dwie odmiany dekoratorów:
Dekoratory funkcji
– wykonują ponowne dowiązania nazw w momencie
definicji funkcji, udostępniając warstwę logiki, która jest w stanie
zarządzać funkcjami oraz metodami bądź ich późniejszymi
wywołaniami.
Dekoratory klas
– wykonują ponowne dowiązania nazw w momencie definicji
klasy, udostępniając warstwę logiki, która jest w stanie zarządzać
klasami bądź instancjami utworzonymi za pomocą ich późniejszego
wywołania.
143 / 212
Dekoratory II
W skrócie
dekoratory udostępniają sposób wstawiania automatycznie wykonywanego kodu na
końcu instrukcji definicji funkcji oraz klas.
Jak większość zaawansowanych konstrukcji pythona, dekoratory nigdy nie są
wymagane, ale używając ich można osiągnąć cel pisząc mniejszą ilość
czytelniejszego kodu.
Dekoratory mają łatwą do zauważenia, czytelna składnię
Dla danego rozwiązania dekorator stosuje się tylko raz przy definicji funkcji
lub klasy
Ogólny przykład dekoratora:
144 / 212
Dekoratory III
Listing 69: Ogólna składnia dekoratora [5]
1
@decorator
# Udekorowanie funkcji
2
def
F
(arg):
3
...
4
F(
99
)
# Wywołanie funkcji
5
def
F
(arg):
6
...
7
F = decorator(F)
# Ponowne dowiązanie nazwy funkcji do wyniku dekoratora
8
F(
99
)
# Wywołuje decorator(F)(99)
składnia z linii 1-3 listingu 69 odwzorowywana jest na jej normalny odpowiednik
widoczny w liniach 7 i 8.
145 / 212
Dekoratory IV
Dekorator jest obiektem wywoływalnym zwracającym obiekt wywoływalny.
Oznacza to, że zwraca on obiekt, który będzie wywołany później, kiedy
udekorowana funkcja wywoływana jest za pomocą oryginalnej nazwy. Zwracany
obiekt jest albo obiektem opakowującym przechwytującym późniejsze wywołania,
albo w jakiś sposób rozszerzoną oryginalną funkcją
Listing 70: Z dekoratorem [5]
1
def
decorator
(F):
# W momencie dekoracji @
2
def
wrapper
(*args):
# W momencie wywołania opakowanej fun.
3
# Użycie F oraz args
4
# F(*args) wywołuje oryginalną funkcję
5
return
wrapper
6
@decorator
# func = decorator(func)
7
def
func
(x, y):
# func przekazywane do F dekoratora
8
...
9
func(
6
,
7
)
# 6, 7 przekazywane do *args obiektu opakowującego
Listing 71: Bez dekoratora [5]
1
class
decorator
:
2
def
__init__
(
self
, func):
# W momencie dekoracji @
3
self
.func = func
4
def
__call__
(
self
, *args):
# W momencie wywoł. opakowanej funk.
5
# Użycie self.func oraz args
6
# self.func(*args) wywołuje oryginalną funkcję
7
@decorator
8
def
func
(x, y):
# func = decorator(func)
9
...
# func przekaz. jest do __init__
10
func(
6
,
7
)
# 6, 7 przekaz. do *args dla __call__
146 / 212
Dekoratory klas I
Dekorator klasy
Dekorator klasy przechwytuje wywołanie nazwy klasy w celu utworzenia instancji
tak, że wywołujący otrzymuje nie oryginalną klasę, ale obiekt zwrócony przez
dekorator.
Listing 72: Dekorator klasy: deklaracja i działanie [5]
1
@decorator
# Udekorowanie klasy
2
class
C
:
3
...
4
x = C(
99
)
# Utworzenie instancji
5
"""
6
a naprawdę dzieje się to:
7
"""
8
class
C
:
9
...
10
C = decorator(C)
# Ponowne dowiązanie nazwy klasy do wyniku dekoratora
11
x = C(
99
)
# Tak naprawdę wywołuje decorator(C)(99)
147 / 212
Dekoratory funkcji wbudowanych
Dekoratory funkcji wbudowanych I
A teraz coś mniej zakręconego, kilka częstych i praktycznych zastosowań
dekoratorów.
Metoda statyczna
Listing 73: Metoda statyczna [5]
1
class
Spam
:
2
numInstances =
0
3
def
__init__
(
self
):
4
Spam.numInstances = Spam.numInstances +
1
5
@staticmethod
6
def
printNumInstances
():
# tu prawidłowo bez self!!!
7
(
"Liczba utworzonych instancji: "
, Spam.numInstances)
8
a = Spam()
9
b = Spam()
10
c = Spam()
11
Spam.printNumInstances()
# Teraz działają wywołania z klas i z instancji!
12
a.printNumInstances()
# Obydwa wypiszą "Liczba utworzonych instancji: 3"
Metoda klasy
148 / 212
Dekoratory funkcji wbudowanych
Dekoratory funkcji wbudowanych II
Listing 74: Metoda klasy
1
class
Methods
:
2
def
imeth
(
self
, x):
# Zwykła metoda instancji: otrzymuje self
3
(
self
, x)
4
@staticmethod
5
def
smeth
(x):
# Metoda statyczna: instancja nie jest przekazywana
6
(x)
7
@classmethod
8
def
cmeth
(cls, x):
# Metoda klasy: otrzymuje klasę, nie instancję
9
(cls, x)
Właściwości
149 / 212
Dekoratory funkcji wbudowanych
Dekoratory funkcji wbudowanych III
Listing 75: Właściwości definiowane przez dekoratory [3]
1
class
C
(
object
):
2
def
__init__
(
self
):
3
self
._x =
None
4
@property
5
def
x
(
self
):
6
"""I'm the 'x' property."""
7
return
self
._x
8
@x.setter
9
def
x
(
self
, value):
10
self
._x = value
11
@x.deleter
12
def
x
(
self
):
13
del
self
._x
150 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Wykład 8
Klasy – deskryptory, zarządzanie
atrybutami, metody specjalne
Thawte Consulting
Python makes us extremely productive, and makes maintaining a large and rapidly
evolving codebase relatively simple, said Mark Shuttleworth.
151 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas I
Zarządzanie dostępem do atrybutów:
funkcja standardowa
property()
służąca do obsługi atrybutów przez
mechanizm właściwości, definiowanie właściwości przy użyciu dekoratorów
jest odmianą tej metody
protokół deskryptora – służący do przekierowania dostępu do
uszczegółowionych atrybutów do instancji klas z własnymi metodami
programów obsługi pobierania i ustawiania
metody
__getattr__
i
__getattr__
– służą do przekierowania
niezdefiniowanych pobrań atrybutów, a także wszystkich przypisań atrybutów
metoda
__getattribute__
– służąca do przekierowania wszystkich pobrań
atrybutów do ogólnej metody programu obsługi w klasach nowego stylu (3.0)
152 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory I
Deskryptory
Deskryptory stanowią alternatywny sposób przechwytywania dostępu do atrybutów
i są mocno powiązane z właściwościami. Tak naprawdę właściwość jest rodzajem
deskryptora — funkcja wbudowana
property()
jest uproszczonym sposobem
tworzenia określonego typu deskryptora, który wykonuje funkcje metod
w momencie dostępu do atrybutów.
Deskryptory tworzone są jako niezależne klasy i są przypisywane do atrybutów
klas tak samo jak funkcje metod.
Tak jak wszystkie inne atrybuty klas, są one dziedziczone przez klasy
podrzędne oraz instancje.
Do ich metod przechwytujących operacje dostępu przekazywane są zarówno
sam deskryptor (w postaci argumentu
self
), jak i instancje klasy klienta.
Z tego powodu zachowują i wykorzystują własne informacje o stanie, a także
informacje o stanie podmiotowej instancji.
153 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory II
Metody pobierania (
__get__
), ustawiania (
__set__
) oraz usuwania
(
__delete__
) w klasie deskryptora są wykonywane automatycznie w momencie
wystąpienia odpowiedniego typu dostępu do atrybutu przypisanego do instancji
klasy deskryptora.
Listing 76: Ogólna składnia deskryptora [5]
1
class
Descriptor
:
2
"miejsce na łańcuch znaków dokumentacji"
3
def
__get__
(
self
, instancja, w
ł
a
ś
ciciel): ...
# Zwraca wartość atrybutu
4
def
__set__
(
self
, instancja, w
ł
a
ś
ciciel): ...
# Nic nie zwraca (None)
5
def
__delete__
(
self
, instancja): ...
# Nic nie zwraca (None)
Argumenty deskryptorów
Do metod deskryptorów przekazywana jest zarówno: instancja klasy deskryptora
(
self
), jak i instancja klasy klienta (
instancja
), do której dołączana jest
instancja deskryptora.
154 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory III
Listing 77: Deskryptor jako właściwość [5]
1
>>>
class
Descriptor
(
object
):
2
...
def
__get__
(
self
, instance, owner):
3
...
(
self
, instance, owner, sep=
'\n'
)
4
...
5
>>>
class
Subject
:
6
...
attr = Descriptor()
# Instancja klasy Descriptor jest atrybutem klasy
7
...
8
>>> X = Subject()
9
>>> X.attr
Deskryptory tylko do odczytu
By uczynić atrybut oparty na deskryptorze atrybutem tylko do odczytu, należy
przechwycić przypisanie w klasie deskryptora i zgłosić wyjątek, tak by zapobiec
przypisaniu atrybutu. Brak metody
__set__
powoduje, że podczas przypisana
następuje przesłonięcie deskryptora.
155 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory IV
Listing 78: Prawidłowy deskryptor tylko do odczytu [5]
1
>>>
class
D
:
2
...
def
__get__
(*args):
(
'pobranie'
)
3
...
def
__set__
(*args):
raise
AttributeError(
'nie można ustawić'
)
4
...
5
>>>
class
C
:
6
...
a = D()
7
...
8
>>> X = C()
9
>>> X.a
# Przekierowane do C.a.__get__
10
pobranie
11
>>> X.a =
99
# Przekierowane do C.a.__set__
12
AttributeError: nie mo
ż
na ustawi
ć
156 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory V
Listing 79: Stan deskryptora [5]
1
class
DescSquare
:
2
def
__init__
(
self
, start):
# Każdy deskryptor ma własny stan
3
self
.value = start
4
def
__get__
(
self
, instance, owner):
# Przy pobieraniu atrybutów
5
return
self
.value **
2
6
def
__set__
(
self
, instance, value):
# Przy przypisywaniu atrybutów
7
self
.value = value
# Brak usuwania i dokumentacji
8
class
Client1
:
9
X = DescSquare(
3
)
# Przypisanie instancji deskryptora do atrybutu klasy
10
class
Client2
:
11
X = DescSquare(
32
)
# Inna instancja w innej klasie klienta
12
# Można także utworzyć kod dwóch instancji tej samej klasy
13
c1 = Client1()
14
c2 = Client2()
15
(c1.X)
# 3 ** 2
16
c1.X =
4
17
(c1.X)
# 4 ** 2
18
(c2.X)
# 32 ** 2
157 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne klas – deskryptory VI
Praktyczne stosowanie deskryptorów
Zwykle rzadko korzysta się z deskryptorów, gdyż korzystanie z właściwości
definiowanych przy użyciu dekoratorów wydaja się być wygodniejsze. Znajomość
deskryptorów jest jednak przydatna przy używaniu zaawansowanych mechanizmów
pythona jak np.
__slots__
158 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne –
__getattr__
i
__getattribute__
I
Metody przeciążania operatorów
__getattr__
oraz
__getattribute__
udostępniają jeszcze inne sposoby przechwytywania pobrań atrybutów dla instancji
klas. Tak jak właściwości oraz deskryptory, pozwalają one wstawiać kod, który
będzie wykonywany w momencie dostępu do atrybutów.
Metody
__getattr__
,
__setattr__
i
__delattr__
wykonywane są dla
atrybutów niezdefiniowanych, to znaczy atrybutów nieprzechowywanych
w instancji lub dziedziczonych po jednej z jej klas.
Metoda
__getattribute__
i
__setattribute__
wykonywana jest dla
każdego atrybutu, dlatego wykorzystując ją, trzeba uważać i unikać pętli
rekurencyjnych przy przekazywaniu dostępu do atrybutów do klasy
nadrzędnej.
159 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne –
__getattr__
i
__getattribute__
II
Listing 80: Śledzenie odczytów i przypisań [5]
1
class
Catcher
:
2
def
__getattr__
(
self
, name):
3
(
'Pobranie:'
, name)
4
def
__setattr__
(
self
, name, value):
5
(
'Ustawienie:'
, name, value)
6
X = Catcher()
7
X.job
# Wyświetla "Pobranie: job"
8
X.pay
# Wyświetla "Pobranie: pay"
9
X.pay =
99
# Wyświetla "Ustawienie: pay 99"
Metody te pozwalają na śledzenie i kontrolowanie odczytów i przypisań wybranych
bądź wszystkich atrybutów klas. Można ten mechanizm wykorzystać również do
zablokowywania możliwości rozszerzania klasy.
160 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne –
__getattr__
i
__getattribute__
III
Listing 81: Metoda __setattr__ użyta do blokady dodawania nowych atrybutów
do klasy
1
class
Test
(
object
):
2
def
__init__
(
self
):
3
self
.a =
1
4
def
__setattr__
(
self
, name, value):
5
if
name
in
{
'a'
,
'b'
,
'c'
}:
6
self
.__dict__[name] = value
7
else
:
8
raise
(AttributeError),
u"Nie można dodać atrybutu"
9
X = Test()
10
(X.a)
# 1
11
X.a =
10
12
(X.a)
# 10
13
X.b =
11
14
(X.b)
# AttributeError
15
X.x =
12
161 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Metody specjalne –
__getattr__
i
__getattribute__
IV
Metody te należy używać z dużą ostrożnością gdyż można łatwo doprowadzić do
pętli rekurencyjnej.
Listing 82: Pętle rekurencyjne i ich unikanie [5]
1
def
__getattribute__
(
self
, name):
2
x =
self
.other
# PĘTLA!
3
def
__getattribute__
(
self
, name):
4
x =
object
.__getattribute__(
self
,
'other'
)
# Wymuszenie klasy wyżej w celu uniknięcia siebie
5
def
__setattr__
(
self
, name, value):
6
self
.other = value
# PĘTLA!
7
def
__setattr__
(
self
, name, value):
8
self
.__dict__[
'other'
] = value
# Użycie słownika atrybutów w celu uniknięcia siebie
162 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Atrybuty specjalne klas [3] I
object.__dict__
– słownik przechowujący zapisywalne atrybuty obiektu
instance.__class__
– klasa do której należy instancja obiektu
class.__bases__
– krotka klas bazowych klasy
class.__name__
– nazwa klasy lub typu
class.__mro__
–
class.mro()
– krotka (uporządkowana) zawierające klasy które są
analizowane podczas wyszukiwania metod
class.__subclasses__()
– lista bezpośrednich podklas, które istnieją
dir(object)
– lista atrybutów obiektu
163 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Inne ważne metody specjalne klas [3] I
object.__new__(cls[, ...])
– konstruktor (właściwy) wywoływany
(zwykle niejawnie) do tworzenia nowej instancji obiektu. Zwraca utworzoną
instancję obiektu. Jest to metoda statyczna, do której należy przekazać klasę
tworzonego obiektu.
object.__init__(self[, ...])
– inicjalizator (pseudokonstruktor) klasy
automatycznie wywoływany przy tworzeniu instancji obiektu
object.__del__(self)
– finalizator klasy (pseudodestruktor), wywoływany
automatycznie przy usuwaniu instancji, rzadko używany i zwykle zbędny
object.__repr__(self)
– zwraca oficjalną tekstową reprezentację obiektu,
zostanie wywołana, gdy użyjemy
repr(obiekt)
.
repr
jest wbudowaną
funkcją Pythona, która zwraca reprezentację danego obiektu w postaci
łańcucha znaków. Działa dla dowolnych obiektów, nie tylko obiektów klas.
Gdy w oknie interaktywnym wpisujemy nazwę zmiennej i naciskamy ENTER,
Python używa
repr
do wyświetlenia wartości zmiennej.
164 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Inne ważne metody specjalne klas [3] II
object.__str__(self)
– służy do wytwarzania tekstowej reprezentacji
obiektu. Jest automatycznie wywoływana np. przez polecenie
. Zwykle
jest implementowana tak, aby uzyskać opis obiektu w postaci wygodnej dla
użytkownika.
object.__hash__(self)
– wywoływana dla obiektów–kolekcji
hashowalnych czyli wywodzących się od
set
,
frozenset
i
dict
. Metoda
zwraca liczbe całkowitą.
object.__nonzero__(self)
– metoda wywoływana przy sprawdzaniu
wartości logicznej, powinna zwracać
True
lub
False
albo
0
lub
1
, jeśli nie
jest zaimplementowana to wywoływana jest metoda
__len__
object.__len__(self)
– zwraca długość obiektów-kontenerów
metody obsługi kontenerów:
__getitem__
,
__setitem__
,
__delitem__
,
__iter__
,
__reversed__
,
__contains__
,
__getslice__
,
__setslice__
,
__delslice__
Wybrane metody operatorów arytmetycznych:
object.__add__(self, other)
: + -> x + y ->
x.__add__(y)
165 / 212
Klasy – deskryptory, zarządzanie atrybutami, metody specjalne
Inne ważne metody specjalne klas [3] III
object.__sub__(self, other)
: -
object.__mul__(self, other)
: *
object.__floordiv__(self, other)
: //
object.__mod__(self, other)
: %
object.__divmod__(self, other)
:
divmod()
object.__pow__(self, other[, modulo])
:
pow()
, **
object.__lshift__(self, other)
: «
object.__rshift__(self, other)
: »
object.__and__(self, other)
: &
object.__xor__(self, other)
:
̂
object.__or__(self, other)
: |
166 / 212
Wzorce projektowe – realizacja w pythonie
Wykład 9
Wzorce projektowe – realizacja
w pythonie
Christopher Alexander
Każdy wzorzec opisuje problem powtarzający się w danym środowisku i istotę
rozwiązania tego problemu w taki sposób, że można wykorzystać określone
rozwiązanie milion razy i nigdy nie zrobić tego tak samo.
167 / 212
Wzorce projektowe – realizacja w pythonie
Wzorce projektowe – podział I
Co to jest wzorzec projektowy?
Określenie tego co jest, a co nie jest wzorcem,zależy od punktu widzenia, co jedna osoba
uzna za wzorzec dla innej może być tylko prostym blokiem konstrukcyjnym. Zwykle za
wzorce przyjmuje się opisy komunikujących się obiektów i klas przeznaczonych do
rozwiązywania ogólnych problemów projektowych w określonym kontekście.
Podział wzorców projektowych:
Rodzaj
Konstrukcyjne
Strukturalne
Operacyjne
Zasięg
Klasa
Metoda wytwórcza
Adapter
Interpreter
Metoda szablonowa
Klasa
Fabryka abstrakcyjna
Adapter
Łańcuch zobowiązań
Budowniczy
Most
Polecenie
Prototyp
Kompozyt
Iterator
Singleton
Dekorator
Mediator
Fasada
Pamiątka
Pyłek
Obserwator
Pełnomocnik
Stan
Strategia
Odwiedzający
168 / 212
Wzorce projektowe – realizacja w pythonie
Wzorce projektowe – podział II
Uwaga 1.
Wiele wzorców projektowych ma zbliżoną funkcjonalność, ale realizowana rożnymi
metodami, wiele też z nich jest ze sobą powiązanych. Dlatego często się zdarza,
ze zastosowanie jednego wzorca implikuje wybór kolejnych wzorców.
Uwaga 2.
Z uwagi na różnice w obiektowości w rożnych językach programowania rozwiązania
poszczególnych wzorców mogą się nieco różnić w konkretnych implementacjach.
169 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] I
Typ: obiektowy, strukturalny
Inne nazwy: nakładka (wrapper)
Przeznaczenie
Dynamicznie dołącza dodatkowe obowiązki do obiektu. Wzorzec ten udostępnia
alternatywny elastyczny sposób tworzenia podklas o wzbogaconych funkcjach.
Typowa realizacja polega na (dynamicznym) umieszczeniu komponentu w innym
obiekcie (zewnętrznym). Ten zewnętrzny obiekt to dekorator, który musi być
zgodny z interfejsem ozdabianego obiektu – dzięki temu jego obecność jest
niezauważalna dla dla klientów danego komponentu. Dekorator przekazuje żądania
do komponentu, a przed ich wysłaniem, bądź potem może wykonać dodatkowe
działania. Taka przezroczystość daje możliwość rekurencyjnego zagnieżdżania
dekoratorów.
170 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] II
Rysunek:
Diagram klas dla wzorca Dekorator [2]
Wzorzec dekoratora a dziedziczenie
Wzorzec dekoratora daje funkcjonalność, którą inaczej można uzyskać przez
dziedziczenie. Ponieważ dziedziczenie jest statyczne, to dekorator zapewniając
możliwość dynamicznej podmiany obiektu jest rozwiązanie elastyczniejszym i
powinien być rozwiązaniem preferowanym.
171 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] III
Przykład: Mamy funkcję (w pythonie to też obiekt!) która realizuje komunikację
po gniazdach TCP. Chcemy wzbogacić ją o logowanie na kilka sposobów.
Listing 83: Kod serwera czekającego na podłączenie klienta [2]
1
import
socket
2
def
respond
(client):
3
response =
input
(
"Enter a value: "
)
4
client.send(
bytes
(response,
'utf8'
))
5
client.close()
6
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
7
server.bind((
'localhost'
,
2401
))
8
server.listen(
1
)
9
try
:
10
while
True
:
11
client, addr = server.accept()
12
respond(client)
13
finally
:
14
server.close()
172 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] IV
Listing 84: Kod klienta [2]
1
import
socket
2
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3
client.connect((
'localhost'
,
2401
))
4
(
"Received: {0}"
.format(client.recv(
1024
)))
5
client.close()
173 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] V
Listing 85: Kod klasy logującej [2]
1
class
LogSocket
:
2
def
__init__
(
self
, socket):
3
self
.socket = socket
4
def
send
(
self
, data):
5
(
"Sending {0} to {1}"
.format(
6
data,
self
.socket.getpeername()[
0
]))
7
self
.socket.send(data)
8
def
close
(
self
):
9
self
.socket.close()
Użycie wzorca dekoratora nastąpi przez zastąpienie wywołania
respond(client)
z kodu serwera (listing 83) wywołaniem
respond(LogSocket(client))
.
Właściwa moc wzorca dekorator ujawnia się, kiedy potrzebne jest zastosowanie
kilku dynamicznie zamienianych obiektów.
174 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] VI
Listing 86: Kod drugiej klasy logującej [2]
1
import
gzip
2
from
io
import
BytesIO
3
class
GzipSocket
:
4
def
__init__
(
self
, socket):
5
self
.socket = socket
6
def
send
(
self
, data):
7
buf = BytesIO()
8
zipfile = gzip.GzipFile(fileobj=buf, mode=
"w"
)
9
zipfile.write(data)
10
zipfile.close()
11
self
.socket.send(buf.getvalue())
12
def
close
(
self
):
13
self
.socket.close()
175 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] VII
W tym przykładzie najpierw sprawdzane jest czy ma być zastosowane logowanie
i jeśli tak to klient jest dekorowany odpowiednim obiektem. Następnie sprawdzane
jest czy klient obsługuje skompresowane transmisje i jeśli tak to klient jest
dekorowany obiektem realizującym kompresję. Linia
response(client)
,
w zależności od ustawień
client
może być jednym z czterech różnych obiektów.
176 / 212
Wzorce projektowe – realizacja w pythonie
Dekorator – Decorator [4] VIII
Listing 87: Dynamiczne podmienianie dekoratora
1
log_send =
True
2
#compress_hosts = ('127.0.0.1', 'localhost')
3
compress_hosts = (
None
,)
4
try
:
5
while
True
:
6
client, addr = server.accept()
7
clientNb = client.getpeername()
# uwaga - to zmienione względem przykładu
8
if
log_send:
9
client = LoggingSocket(client)
10
if
clientNb[
0
]
in
compress_hosts:
11
client = GzipSocket(client)
12
respond(client)
13
finally
:
14
server.close()
Wzorzec dekoratora a dekorator @
Dekoratory stosowane w pythonie (poprzedzone znakiem @) w szerokim zakresie
i za pomocą oszczędnej składni realizują wzorzec dekoratora.
177 / 212
Wzorce projektowe – realizacja w pythonie
Obserwator – Observer [4] I
Typ: obiektowy, operacyjny,
Inne nazwy: obiekty zależne (dependents), publikuj-suskrybuj (publish-subscribe)
Przeznaczenie
Określa zależność jeden do wielu między obiektami. Kiedy zmieni się stan jednego
z obiektów, wszystkie obiekty zależne od niego są o tym fakcie automatycznie
powiadamiane i aktualizowane. Każdy obserwator może być odpowiedzialny za
inny element obserwowany. Obiekt obserwowany nie zna szczegółów
obserwatorów, jedynie wywołuje domyślną metodę.
Wzorzec obserwatora jest użyteczny przy monitoringu stanu lub przechwytywania
zdarzeń. Ten wzorzec opisuje sposób, w którym pojedynczy obiekt, może być
obserwowany przez zbiór obiektów – obserwatorów. Jeżeli nastąpi zmiana
obserwowanej wartości obiekt obserwowany wywołuje powiadamiającą obserwatory.
178 / 212
Wzorce projektowe – realizacja w pythonie
Obserwator – Observer [4] II
Rysunek:
Diagram klas dla wzorca Obserwator [2]
Typowa realizacja:
Odwzorowanie podmiotów na obserwatory. Najprostszy sposób na śledzenie
w podmiocie obserwatorów otrzymujących powiadomienia polega na
przechowywaniu referencji do nich bezpośrednio w podmiocie. To podejście
jest dość kosztowne jeśli istnieje wiele podmiotów i nieliczne obserwatory.
Można zamienić koszty pamięciowe na koszty czasowe przez zastosowanie
wyszukiwania zamiast przechowywania.
179 / 212
Wzorce projektowe – realizacja w pythonie
Obserwator – Observer [4] III
Obserwowanie więcej niż jednego podmiotu. W niektórych przypadkach
uzasadnione jest uzależnianie obserwatora od więcej niż jednego podmiotu
(np. obiekt zależny od kilku źródeł danych). Konieczne jest wówczas
określenie interfejsu aktualizacji aby wyłapać, który podmiot wysłał
powiadomienie.
Przykład: W przykładzie zostanie zbudowany obiekt obserwowany
Inventory
(inwentarz), które będzie miał właściwości
product
i
quantity
. Ustawienie nowej
wartości w którejkolwiek z tej właściwości powoduje wywołanie metody
_update_observers
. Metoda ta wywoła domyślną akację dla wszystkich
podpiętych obserwatorów (zdefiniowana metodą specjalną
__call__
)
180 / 212
Wzorce projektowe – realizacja w pythonie
Obserwator – Observer [4] IV
Listing 88: Obiekt obserwowany
1
class
Inventory
(
object
):
2
def
__init__
(
self
):
3
self
.observers = []
4
self
._product =
None
5
self
._quantity =
0
6
def
attach
(
self
, observer):
7
self
.observers.append(observer)
8
@property
9
def
product
(
self
):
10
return
self
._product
11
@product.setter
12
def
product
(
self
, value):
13
self
._product = value
14
self
._update_observers()
15
@property
16
def
quantity
(
self
):
17
return
self
._quantity
18
@quantity.setter
19
def
quantity
(
self
, value):
20
self
._quantity = value
21
self
._update_observers()
22
def
_update_observers
(
self
):
23
for
observer
in
self
.observers:
24
observer()
Listing 89: Obserwator
1
class
ConsoleObserver
(
object
):
2
def
__init__
(
self
, inventory):
3
self
.inventory = inventory
4
def
__call__
(
self
):
5
(
self
.inventory.product)
6
(
self
.inventory.quantity)
Listing 90: Użycie obserwatora
1
>>> i = Inventory()
2
>>> c = ConsoleObserver(i)
3
>>> i.attach(c)
4
>>> i.product =
"Widget"
5
Widget
6
0
7
>>> i.quantity =
5
8
Widget
9
5
181 / 212
Wzorce projektowe – realizacja w pythonie
Obserwator – Observer [4] V
Listing 91: Użycie wielu obserwatorów
1
>>> i = Inventory()
2
>>> c1 = ConsoleObserver(i)
3
>>> c2 = ConsoleObserver(i)
4
>>> i.attach(c1)
5
>>> i.attach(c2)
6
>>> i.product =
"Gadget"
7
Gadget
8
0
9
Gadget
10
0
11
>>> i.quantity =
2
12
Gadget
13
2
14
Gadget
15
2
16
>>>
182 / 212
Wzorce projektowe – realizacja w pythonie
Strategia – Strategy [4] I
Typ: obiektowy, operacyjny,
Inne nazwy: polityka (policy))
Przeznaczenie
Określa rodzinę algorytmów, kapsułkuje każdy z nich i umożliwia ich zamienne
stosowanie. Wzorzec ten pozawala zmieniać algorytmy niezależnie od
korzystających z nich klientów.
Wzorzec
Strategia
zwykle realizowany jest w ten sposób, że działania, które
można wykonać na kilka sposobów są zaimplementowane w osobnych klasach,
które implementują wspólną klasę abstrakcyjną. Obiekt korzystający ze zmiennych
strategii odwołuje się do klasy abstrakcyjnej (kompozycja), w miejsce której
wstawiane są odpowiednie strategie.
183 / 212
Wzorce projektowe – realizacja w pythonie
Strategia – Strategy [4] II
Rysunek:
Diagram klas dla wzorca Strategia [2]
Wzorca strategia używa się zwykle:
Kiedy wiele powiązanych klas rożni się tylko zachowaniem. Strategie
umożliwiają skonfigurowanie klasy za pomocą jednego z wielu zachowań.
Kiedy potrzebne są różne wersje algorytmu, np. związanych z różnymi
kosztami czasowymi lub pamięciowymi.
Jeżeli algorytm korzysta z danych, o których klienty nie powinny wiedzieć.
Wzorzec strategia pozwala unikać ujawniania złożonych, specyficznych dla
algorytmu struktur danych.
184 / 212
Wzorce projektowe – realizacja w pythonie
Strategia – Strategy [4] III
Gdy klasa definiuje wiele zachowań, a te w operacjach pojawiają się w formie
złożonych instrukcji warunkowych. Zamiast tworzyć wiele takich instrukcji
należy przenieść powiązane zachowania do odrębnych klas strategii.
Przykład: Strategie rozmieszczania tapety na pulpicie: sąsiadująco (Tiled),
wyśrodkowany (Centered), dopasowany (Scaled)
Listing 92: Strategia I
1
from
pygame
import
image
2
from
pygame.transform
import
scale
3
from
pygame
import
Surface
4
class
TiledStrategy
:
5
def
make_background
(
self
, img_file, desktop_size):
6
in_img = image.load(img_file)
7
out_img = Surface(desktop_size)
8
for
x
in
range
((out_img.get_width()//in_img.get_width())+
1
):
9
for
y
in
range
((out_img.get_height()//in_img.get_height())+
1
):
10
out_img.blit(in_img, (in_img.get_width()*x, in_img.get_height()*y))
11
return
out_img
185 / 212
Wzorce projektowe – realizacja w pythonie
Strategia – Strategy [4] IV
Listing 93: Strategia II
1
class
CenteredStrategy
:
2
def
make_background
(
self
, img_file, desktop_size):
3
in_img = image.load(img_file)
4
out_img = Surface(desktop_size)
5
out_img.fill((
0
,
0
,
0
))
6
left = (out_img.get_width() - in_img.get_width()) /
2
7
top = (out_img.get_height() - in_img.get_height()) /
2
8
out_img.blit(in_img, (left, top))
9
return
out_img
Listing 94: Strategia III
1
class
ScaledStrategy
:
2
def
make_background
(
self
, img_file, desktop_size):
3
in_img = image.load(img_file)
4
return
scale(in_img, desktop_size)
186 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] I
Typ: obiektowy, operacyjny,
Inne nazwy: obiekty stanów (object of states))
Przeznaczenie
Umożliwia obiektowi modyfikację zachowania w wyniku zmiany wewnętrznego
stanu. Wygląda to tak jakby obiekt zmienił klasę.
Rysunek:
Diagram klas dla wzorca Stan [2]
187 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] II
Wzorzec
Stan
jest podobny w swej strukturze do wzorca
Strategia
. Różni się
jednak przeznaczeniem i zachowaniem. Stosuje się go gdy:
Zachowania obiektu zależy od jego stanu, a obiekt musi na podstawie stanu
zmieniać działanie w czasie wykonywania programu.
Operacje podejmują długie, wieloczęściowe instrukcje warunkowe zależne od
stanu obiektu. Takie stany są zwykle reprezentowane przez stałe
wyliczeniowe. Często kilka operacji obejmuje tę samą strukturę warunkową.
Wzorzec
Stan
powoduje umieszczenie każdej gałęzi takiej struktury w
odrębnej klasie. Umożliwia to traktowanie stanu jako samodzielnego obiektu,
który można modyfikować niezależnie od innych obiektów.
188 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] III
Listing 95: Plik XML do przetwarzania
1
<book>
2
<author>
Dusty Phillips
</author>
3
<publisher>
Packt Publishing
</publisher>
4
<title>
Python 3 Object Oriented Programming
</title>
5
<content>
6
<chapter>
7
<number>
1
</number>
8
<title>
Object Oriented Design
</title>
9
</chapter>
10
<chapter>
11
<number>
2
</number>
12
<title>
Objects In Python
</title>
13
</chapter>
14
</content>
15
</book>
189 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] IV
Listing 96: Klasa węzła XML
1
class
Node
:
2
def
__init__
(
self
, tag_name,
3
parent=
None
):
4
self
.parent = parent
5
self
.tag_name = tag_name
6
self
.children = []
7
self
.text=
""
8
def
__str__
(
self
):
9
if
self
.text:
10
return
self
.tag_name +
": "
11
+
self
.text
12
else
:
13
return
self
.tag_name
Listing 97: Klasa parsera
1
class
Parser
:
2
def
__init__
(
self
, parse_string):
3
self
.parse_string = parse_string
4
self
.root =
None
5
self
.current_node =
None
6
self
.state = FirstTag()
7
def
process
(
self
, remaining_string):
8
remaining =
self
.state.process(
9
remaining_string,
self
)
10
if
remaining:
11
self
.process(remaining)
12
def
start
(
self
):
13
self
.process(
self
.parse_string)
190 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] V
Listing 98: Klasa stanu FirstTag
1
class
FirstTag
:
2
def
process
(
self
, remaining_string, parser):
3
i_start_tag = remaining_string.find(
'<'
)
4
i_end_tag = remaining_string.find(
'>'
)
5
tag_name = remaining_string[i_start_tag+
1
:i_end_tag]
6
root = Node(tag_name)
7
parser.root = parser.current_node = root
8
parser.state = ChildNode()
9
return
remaining_string[i_end_tag+
1
:]
191 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] VI
Listing 99: Klasa obsługi węzła potomnego
1
class
ChildNode
:
2
def
process
(
self
, remaining_string, parser):
3
stripped = remaining_string.strip()
4
if
stripped.startswith(
"</"
):
5
parser.state = CloseTag()
6
elif
stripped.startswith(
"<"
):
7
parser.state = OpenTag()
8
else
:
9
parser.state = TextNode()
10
return
stripped
192 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] VII
Listing 100: Klasa stanu OpenTag
1
class
OpenTag
:
2
def
process
(
self
, remaining_string, parser):
3
i_start_tag = remaining_string.find(
'<'
)
4
i_end_tag = remaining_string.find(
'>'
)
5
tag_name = remaining_string[i_start_tag+
1
:i_end_tag]
6
node = Node(tag_name, parser.current_node)
7
parser.current_node.children.append(node)
8
parser.current_node = node
9
parser.state = ChildNode()
10
return
remaining_string[i_end_tag+
1
:]
193 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] VIII
Listing 101: Klasa stanu CloseTag
1
class
CloseTag
:
2
def
process
(
self
, remaining_string, parser):
3
i_start_tag = remaining_string.find(
'<'
)
4
i_end_tag = remaining_string.find(
'>'
)
5
assert
remaining_string[i_start_tag+
1
] ==
"/"
6
tag_name = remaining_string[i_start_tag+
2
:i_end_tag]
7
assert
tag_name == parser.current_node.tag_name
8
parser.current_node = parser.current_node.parent
9
parser.state = ChildNode()
10
return
remaining_string[i_end_tag+
1
:].strip()
Listing 102: Klasa stanu TextNode
1
class
TextNode
:
2
def
process
(
self
, remaining_string, parser):
3
i_start_tag = remaining_string.find(
'<'
)
4
text = remaining_string[:i_start_tag]
5
parser.current_node.text = text
6
parser.state = ChildNode()
7
return
remaining_string[i_start_tag:]
194 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] IX
Listing 103: Procedura uruchamiająca
1
if
__name__ ==
"__main__"
:
2
import
sys
3
with
open
(sys.argv[
1
])
as
file
:
4
contents =
file
.read()
5
p = Parser(contents)
6
p.start()
7
nodes = [p.root]
8
while
nodes:
9
node = nodes.pop(
0
)
10
(node)
11
nodes = node.children + nodes
195 / 212
Wzorce projektowe – realizacja w pythonie
Stan – State [4] X
Listing 104: Rezultat działania programu
1
book
2
author: Dusty Phillips
3
publisher: Packt Publishing
4
title: Python 3 Object Oriented Programming
5
content
6
chapter
7
number: 1
8
title: Object Oriented Design
9
chapter
10
number: 2
11
title: Objects In Python
196 / 212
Wzorce projektowe – realizacja w pythonie
Singleton – Singleton [4] I
Typ: obiektowy, konstrukcyjny,
Przeznaczenie
Gwarantuje, że klasa będzie miała tylko jeden egzemplarz, i zapewnia globalny
dostęp do niego.
Zapewnia kontrolę dostępu do jedynego egzemplarza. Ponieważ klasa
Singleton
kapsułkuje swój jedyny egzemplarz, można w niej ściśle
kontrolować dostęp do niego.
Pozwala zmniejszyć przestrzeń nazw. Zastępuje zmienne globalne.
Klasa
Singleton
ułatwia konfiguracje aplikacji. Można tworzyć
wyspecjalizowane podklasy klasy
Singleton
.
Przez modyfikację klasy
Singleton
można utworzyć klasy o różnych limitach
egzemplarzy.
Jest bardziej elastyczny od operacji statycznych co jest istotne w niektórych
językach programowania.
197 / 212
Wzorce projektowe – realizacja w pythonie
Singleton – Singleton [4] II
Typowa realizacja: Standardowe rozwiązanie polega na ukryciu operacji
tworzącej egzemplarz w operacji statycznej, która gwarantuje, że może powstać
tylko jeden egzemplarz danej klasy. Ta operacja ma dostęp do zmiennej
przechowującej ów egzemplarz, a zanim zwróci jej wartość, upewnia się, że
zmienna została zainicjowana za pomocą niepowtarzalnego egzemplarza.
Singletony
są często stosowane do realizacji obiektów stanu we wzorcu
State
.
Rysunek:
Diagram klas dla wzorca Singleton [2]
198 / 212
Wzorce projektowe – realizacja w pythonie
Singleton – Singleton [4] III
W pythonie tworzenie klasy
Singleton
jest nieco nietypowe (dla pythona), gdyż
wymaga użycia konstruktora
__new__
.
W pythonie czasem zamiast
Singleton
stosuje się zmienne globalne modułu.
Zapewniają one występowanie pojedynczego egzemplarza oraz oszczędzają pamięć
i oszczędzają pracy odśmiecaczowi, ale nie dają pełnych możliwości wzorca
Singleton
np. łatwości tworzenia klas o ograniczonej liczbie egzemplarzy.
Przykład:
Listing 105: Klasa Singleton
1
class
OneOnly
:
2
_singleton =
None
3
def
__new__
(cls, *args, **kwargs):
4
if not
cls._singleton:
5
cls._singleton =
super
(OneOnly, cls
6
).__new__(cls, *args, **kwargs)
7
return
cls._singleton
Listing 106: Użycie klasy Singleton
1
>>> o1 = OneOnly()
2
>>> o2 = OneOnly()
3
>>> o1 == o2
4
True
5
>>> o1
6
<__main__.OneOnly
object
at
0xb71c008c
>
7
>>> o2
8
<__main__.OneOnly
object
at
0xb71c008c
>
199 / 212
Wzorce projektowe – realizacja w pythonie
Metoda szablonowa – Template [4] I
Typ: klasowy, operacyjny,
Przeznaczenie
Określa szkielet algorytmu i pozostawia doprecyzowanie niektórych jego kroków
podklasom. Umożliwia modyfikację niektórych etapów algorytmu w podklasach
bez zmiany jego struktury.
Rysunek:
Diagram klas dla wzorca Metoda szablonowa [2]
200 / 212
Wzorce projektowe – realizacja w pythonie
Metoda szablonowa – Template [4] II
Wzorca
Metoda szablonowa
korzysta się zwykle do:
Do jednorazowego implementowania niezmiennych części algorytmu i
umożliwienia implementowania zmieniających się zachowań w podklasach.
Kiedy wspólne zachowanie dla podklas należy wyodrębnić i umieścić w jednej
klasie, aby uniknąć powielania kodu. Najpierw należy wykryć różnice w
istniejącym kodzie, a następnie umieścić je w w nowych operacjach. Na
zakończenie trzeba zastąpić różniące się fragmenty kodu metodą szablonową
wywołującą jedną z nowych operacji.
Do kontrolowania rozszerzania podklas. Można zdefiniować metodę
szablonową wywołującą w odpowiednich miejscach operacje stanowiące
punkty zaczepienia, co umożliwia rozszerzanie podklas tylko w tych punktach.
Ważne jest aby określić w metodzie szablonowej operacje stanowiące punkty
zaczepienia (można je przesłonić), a które są operacjami abstrakcyjnymi
(trzeba je przesłonić).
Typowa realizacja:
Przykład:
201 / 212
Wzorce projektowe – realizacja w pythonie
Metoda szablonowa – Template [4] III
Listing 107: Dane do przykładu metody szablonowej
1
import
sqlite3
2
conn = sqlite3.connect(
"sales.db"
)
3
conn.execute(
"CREATE TABLE Sales (salesperson text, "
4
"amt currency, year integer, model text, new boolean)"
)
5
conn.execute(
"INSERT INTO Sales values ('Tim', 16000, 2010, 'Honda Fit', 'true')"
)
6
conn.execute(
"INSERT INTO Sales values ('Tim', 9000, 2006, 'Ford Focus', 'false')"
)
7
conn.execute(
"INSERT INTO Sales values ('Gayle', 8000, 2004, 'Dodge Neon', 'false')"
)
8
conn.execute(
"INSERT INTO Sales values ('Gayle', 28000, 2009, 'Ford Mustang', 'true')"
)
9
conn.execute(
"INSERT INTO Sales values ('Gayle', 50000, 2010, 'Lincoln Navigator', 'true')"
)
10
conn.execute(
"INSERT INTO Sales values ('Don', 20000, 2008, 'Toyota Prius', 'false')"
)
11
conn.commit()
12
conn.close()
202 / 212
Wzorce projektowe – realizacja w pythonie
Metoda szablonowa – Template [4] IV
Listing 108: Idea – interfejs ob-
sługi bazy danych
1
class
QueryTemplate
(
object
):
2
def
connect
(
self
):
3
pass
4
def
construct_query
(
self
):
5
pass
6
def
do_query
(
self
):
7
pass
8
def
format_results
(
self
):
9
pass
10
def
output_results
(
self
):
11
pass
12
def
process_format
(
self
):
13
self
.connect()
14
self
.construct_query()
15
self
.do_query()
16
self
.format_results()
17
self
.output_results()
Listing 109: Szablon – wspólna część klasy obsługi
bazy danych
1
import
sqlite3
2
class
QueryTemplate
(
object
):
3
def
connect
(
self
):
4
self
.conn = sqlite3.connect(
"sales.db"
)
5
def
construct_query
(
self
):
6
raise
NotImplementedError()
7
def
do_query
(
self
):
8
results =
self
.conn.execute(
self
.query)
9
self
.results = results.fetchall()
10
def
format_results
(
self
):
11
output = []
12
for
row
in
self
.results:
13
row =[
str
(i)
for
i
in
row]
14
output.append(
", "
.join(row))
15
self
.formatted_results =
"\n"
.join(output)
16
def
output_results
(
self
):
17
raise
NotImplementedError()
203 / 212
Wzorce projektowe – realizacja w pythonie
Metoda szablonowa – Template [4] V
Listing 110: Konkret 1 – implementacja różnic wersja I
1
import
datetime
2
class
NewVehiclesQuery
(QueryTemplate):
3
def
construct_query
(
self
):
4
self
.query =
"select * from Sales where new='true'"
5
def
output_results
(
self
):
6
(
self
.formatted_results)
Listing 111: Konkret 2 – implementacja różnic wersja II
1
import
datetime
2
class
UserGrossQuery
(QueryTemplate):
3
def
construct_query
(
self
):
4
self
.query = (
"select salesperson, sum(amt) "
+
5
" from Sales group by salesperson"
)
6
def
output_results
(
self
):
7
filename =
"gross_sales_{0}"
.format(
8
datetime.date.today().strftime(
"%Y%m%d"
))
9
with
open
(filename,
'w'
)
as
outfile:
10
outfile.write(
self
.formatted_results)
204 / 212
Wzorce projektowe – realizacja w pythonie
Pyłek, Waga Piórkowa (Flyweight)
Pyłek, Waga piórkowa (Flyweight) [4] I
207 / 212
Wzorce projektowe – realizacja w pythonie
Abstrakcyjna fabryka klas (Abstract class factory)
Abstrakcyjna fabryka klas (Abstract class
factory) [4] I
209 / 212
Wzorce projektowe – realizacja w pythonie
Kompozyt (Composition pattern)
Kompozyt (Composition pattern) [4] I
210 / 212
Wzorce projektowe – realizacja w pythonie
Kompozyt (Composition pattern)
Literatura I
[1] Replacements for switch statement in python. Website, stan na dzien:
2013.04.07. http://stackoverflow.com/questions/60208/
replacements-for-switch-statement-in-python.
[2] Philips D. Python 3 Object Oriented Programming. Packt Publishing, 2010.
[3] Python Documentation. Python v2.7.5 documentation, stan na dzien:
2013.10.17. http://docs.python.org/2/index.html.
[4] E. Gamma, R. Helm, R. Johnson, and J Vlissides. Wzorce projektowe –
Elementy oprogramowania obiektowego wielokrotnego użytku. Helion, 2010.
[5] Mark Lutz. Python. Wprowadzenie. Helion Gliwice, 2009.
[6] Mark Lutz and David Ascher. Learning python. O’Reilly Media, 2009.
[7] Peter C Norton, Alex Samuel, Dave Aitel, Eric Foster-Johnson, Leonard
Richardson, Jason Diamond, Aleatha Parker, and Michael Roberts.
Beginning Python. Wrox, 2005.
[8] Mark Pilgrim. Dive Into Python. Apress, 2004. http:
//www.diveintopython.net/download/diveintopython-pdf-5.4.zip.
211 / 212
Wzorce projektowe – realizacja w pythonie
Kompozyt (Composition pattern)
Literatura II
[9] Mark Pilgrim. Zanurkuj w pythonie. Website, stan na dzien: 2013.04.07.
http://pl.wikibooks.org/wiki/Zanurkuj_w_Pythonie.
[10] Guido van Rossum. Pep 3103 – a switch/case statement. Website, stan na
dzien: 2013.04.07. http://www.python.org/dev/peps/pep-3103/.
[11] Guido van Rossum et al. Index of Python Enhancement Proposals (PEPs).
Website, stan na dzien: 2013.04.07. http://www.python.org/dev/peps/.
[12] J. Żygierewicz et al. Programowanie z pythonem/programowanie
zorientowane obiektowo. Website, stan na dzien: 2013.10.23.
http://http://brain.fuw.edu.pl/edu/TI:
Programowanie_z_Pythonem/Programowanie_zorientowane_obiektowo.
212 / 212