kurs-pythona-czesc-iii-software-developers-journal.pdf
(
383 KB
)
Pobierz
PROGRAMOWANIE PYTHON
Kurs Pythona
Odcinek 3: Model obiektowy
Dwa pierwsze odcinki miały za zadanie zapoznać nas
z podstawowymi cechami języka i środowiska Python.
Ostatnią wielką niewiadomą pozostały dla nas klasy.
Po ich poznaniu będziemy mogli uznać, że rozumiemy
fundamenty Pythona. Do dzieła!
Dowiesz się:
• Jak korzystać z wbudowanych oraz bibliotecznych klas i obiektów;
• Jak zbudować własną klasę;
• Czym są dekoratory.
Powinieneś wiedzieć:
• Jak zainstalować i uruchomić interpreter Python 2.6 ;
• Jak używać wbudowanych w Pythona list, słowników, krotek i
zbiorów.
M
odel klasowy Pythona składa się z dość prostej
dami. O funkcjach zdążyliśmy sobie opowiedzieć sporo
już ostatnim razem. Zdążyliśmy też wspomnieć o wbudo-
wanych funkcjach i związanych z nimi funkcjach specjal-
nych mających w nazwie po dwa znaki "_" z przodu i z ty-
łu. W przypadku metod funkcje te nabierają szczególne-
go znaczenia, ponieważ pozwalają klasie implementować
szereg opcjonalnych funkcjonalności takich jak ładna re-
prezentacja tekstowa w metodach
__unicode__
i
__str__
czy możliwość porównywania arytmetycznego ze sobą
różnych obiektów danej klasy, w metodach
__lt__
(mniej-
szy),
__gt__
(większy),
__eq__
(równy) itd.
Jedną z takich metod specjalnych jest metoda
__init__
,
nazywana w pewnym uproszczeniu konstruktorem [1]. To
znaczy, że tworząc nowe obiekty, wywołujemy właśnie tę
metodę:
składni i funkcjonalności, która jest mieszanką
systemów obiektowych znanych w C++, Perlu
i Objective-C. Od każdego z tych modeli różni się jednak
na tyle, że warto przejść przez wszystkie cechy klas py-
thonowych dokładnie.
Podstawowa klasa
Zacznijmy od razu od przykładu. Na Listingu 1 znajduje
się prosty model klasowy, który prezentuje wszystkie pod-
stawowe cechy języka. Prezentowane klasy opisują odpo-
wiednio "grzałkę", "dmuchawę" oraz ich połączenie, czy-
li "suszarkę do włosów". Zwróć uwagę, że mimo tego, że
nie omówiłem jeszcze żadnej kwestii dotyczącej klas, już
jesteś w stanie dużo zrozumieć.
Róbta co chceta
Najbardziej fundamentalną cechą klas i obiektów w Py-
thonie jest to, że nie ma w nich podziału na składowe pu-
bliczne i prywatne. Oznacza to, że każdy użytkownik da-
nego obiektu ma pełen dostęp do wszystkich metod i pól
zadeklarowanych w danej klasie. Użytkownikom Javy,
C++ i C# wyda się to nie do pomyślenia, jednak taka de-
cyzja powoduje szereg bardzo pozytywnych skutków,
o czym powiemy sobie później. Ustalanie, jakie składniki
klasy należą do jej wewnętrznej implementacji, jest możli-
we przez konwencję, zgodnie z którą nazwy takich skład-
ników poprzedza się pojedynczym znakiem "_".
hairdryer = Hairdryer()
normal_heater = Heater()
hot_heater = Heater(max_temp=80)
Jak widać, pierwszym argumentem metody
_ _ init _
_
i wszystkich innych metod w klasach pythonowych
jest
self
, czyli zmienna wskazująca na aktualny obiekt.
Zmienna ta jest wpisywana do argumentów automatycz-
nie podczas wywołania metody, więc nie musimy jej do-
datkowo podawać, np.:
>>> hairdryer.dry(5)
Heating to 40 degrees for 5 minutes.
>>> hairdryer.max_temp
50
Metody
Funkcje znajdujące się wewnątrz klasy nazywamy meto-
54
9/2010
Model obiektowy
tów danej klasy. W klasie Blower w metodzie
__init__()
znajdziemy natomiast pola instancji, czyli takie, które są
zawarte tylko w konkretnym obiekcie (czyli w pojedynczej
instancji danej klasy). Inne języki posiadają podobne roz-
graniczenie, nazywając często pola klasowe statycznymi.
Ciekawą cechą, którą można zaobserwować w przykła-
dzie, jest fakt, że w metodzie
heat()
klasy Heater odwo-
łujemy się do pól klasowych tak, jak gdyby były one pola-
mi instancji. Jest to często używany skrót, który dodatko-
wo pozwala w razie potrzeby na przesłonienie danego po-
la klasowego polem instancji.
Przykład takiej techniki znajduje się w konstruktorze klasy
Heater, gdzie jeżeli podamy opcjonalny argument
max_temp
,
konstruktor przesłoni nam domyślną wartość pola klasowe-
go nowym polem instancji. Powoduje to, że klasa w ogólno-
ści zachowuje swoje domyślne ustawienie, ale obiekty mo-
gą to ustawienie dostosowywać do własnych potrzeb.
>>> hot_heater.max_temp
80
automatycznie dołączy do wykonania metody pierwszy
argument
self
wskazujący na obiekt
hairdryer
. Argu-
ment
45
trai więc do zmiennej
how _ long
.
Niektóre języki umożliwiają przygotowywanie wielu wer-
sji tej samej metody, różniących się typem lub liczbą argu-
mentów. W świecie Pythona taka możliwość nie jest po-
trzebna ze względu na obecność argumentów opcjonal-
nych. Przykład takiego argumentu mamy w konstruktorze
klasy Heater, który przez to możemy wołać zarówno nie
podając żadnych dodatkowych argumentów, jak również
specyfikując niestandardową temperaturę maksymalną.
Pola
W prezentowanym na Listingu 1 przykładzie widać dwa
przykłady pól: klasa Heater prezentuje pola klasowe, czy-
li takie, których wartość jest wspólna dla wszystkich obiek-
Dziedziczenie
Jak widać w naszym przykładzie, Python obsługuje wielo-
krotne dziedziczenie. Jest to funkcjonalność stosunkowo
rzadko wykorzystywana i głównie do "przyklejania" dodat-
kowej funkcjonalności do istniejących klas, tak też zrobili-
śmy w naszym przykładzie, gdzie suszarka jest po prostu
grzałką z dmuchawą.
Klasy, po których dziedziczymy, wymieniamy po prze-
cinku w nawiasach za nazwą klasy. Domyślnie, jeżeli nie
chcemy dziedziczyć z jakiejś klasy, powinniśmy dziedzi-
czyć z klasy
object
. Klasy, które nie dziedziczą po tym ty-
pie, są w świecie Pythona znane jako
klasy starego stylu
i posiadają szereg niewygodnych ograniczeń [2]. Stąd, je-
żeli tylko możemy, powinniśmy dziedziczyć z
object
.
Klasy, po których dziedziczymy w świecie Pythona, na-
zywamy
klasami bazowymi
. W każdym przypadku, kiedy
Listing 1.
Podstawowa struktura klas
class
Heater
(
object
):
min_temp
=
28
max_temp
=
50
def
__init__
(
self
,
max_temp
=
None
):
if
max_temp
:
self
.
max_temp
=
max_temp
def
heat
(
self
,
temp
,
how_long
):
if
self
.
min_temp
<=
temp
<=
self
.
max_temp
:
print
"Heating to"
,
temp
,
print
"degrees for"
,
how_long
,
"minutes."
else
:
raise
ValueError
,
"Temperature out or range."
Listing 2.
Dziedziczenie z wbudowanego typu
class
Blower
(
object
):
def
__init__
(
self
):
self
.
blowing
=
False
>>>
class
AttrDict
(
dict
):
...
def
__getattr__
(
self
,
attr
):
...
try
:
...
return
self
[
attr
]
...
except
KeyError
:
...
return
''
>>>
a
=
AttrDict
()
>>>
a
[
'monty'
]
=
'python'
>>>
a
[
'star'
]
=
'bucks'
>>>
a
{
'star'
:
'bucks'
,
'monty'
:
'python'
}
>>>
a
.
star
'bucks'
>>>
a
.
monty
'python'
>>>
a
.
bill
''
def
blow
(
self
):
self
.
blowing
=
True
def
stop
(
self
):
self
.
blowing
=
False
class
Hairdryer
(
Heater
,
Blower
):
def
__init__
(
self
):
super
(
Hairdryer
,
self
)
.
__init__
()
def
dry
(
self
,
how_long
):
self
.
blow
()
self
.
heat
(
40
,
how_long
)
www.sdjournal.org
55
PROGRAMOWANIE PYTHON
chcemy odnieść się do jakiejś metody lub pola z klasy ba-
zowej, możemy to zrobić bez żadnego kłopotu. Przykład
widać w metodzie
dry()
klasy
Hairdryer
, która odwołuje
się do metod
blow()
i
heat()
zdefiniowanych w klasach
bazowych.
Może się jednak zdarzyć sytuacja, że w aktualnej klasie
definiujemy składnik o takiej samej nazwie jak występu-
jący w klasie bazowej. Wówczas trzeba użyć konstrukcji
super()
, która umożliwia wykonanie metody lub uzyska-
nie dostępu do pola z klasy bazowej [3].
Po wbudowanych typach też można dziedziczyć, co
prezentuje Listing 2. Mamy tam definicję magicznego ty-
pu, który jest jednocześnie słownikiem, ale także udostęp-
nia elementy słownika jako swoje atrybuty. Jest to możliwe
dzięki prostej implementacji specjalnej metody
__getattr_
_
. Dodatkowo w metodzie tej zapewniliśmy, że w przypad-
ku odwołania się do nieistniejącego atrybutu otrzymamy
pusty łańcuch znaków zamiast rzuconego wyjątku.
Listing 3.
Właściwości
>>>
class
Traditional
(
object
):
...
ield
=
'A'
>>>
t
=
Traditional
()
>>>
t
.
ield
'A'
>>>
t
.
ield
=
'B'
>>>
t
.
ield
'B'
>>>
class
Smart
(
object
):
...
_data
=
'A'
... @
property
...
def
ield
(
self
):
...
return
self
.
_data
... @
ield
.
setter
...
def
ield
(
self
,
value
):
...
self
.
_data
=
value
...
>>>
s
=
Smart
()
>>>
s
.
ield
'A'
>>>
s
.
ield
=
'B'
>>>
s
.
ield
'B'
>>>
class
Smart
(
object
):
... @
property
...
def
ield
(
self
):
...
return
'A'
>>>
s
=
Smart
()
>>>
s
.
ield
'A'
Pola są lepsze niż metody
W świecie Pythona bardzo często używaną cechą jest
możliwość bezpośredniego odwołania się do pól danej
klasy czy obiektu. Wywołania typu
osoba.data_urodzenia
lub
samochod.silnik.pojemnoc
są na porządku dziennym.
Takie rozwiązanie ma szereg zalet, z których największą
jest fakt, że tak pisany kod jest bardzo czytelny. Dodatko-
wo przez to, że odwołujemy się bezpośrednio do pola, wy-
konanie takiego żądania jest całkiem wydajne.
Programiści Javy mogą w tym momencie zaalarmować,
że takie zachowanie niesie za sobą zagrożenie! Mianowi-
cie, możliwe, że później zmienimy architekturę naszej kla-
sy i już nie będzie można bezpośrednio pobrać daty uro-
dzenia danej osoby z pola, ale trzeba będzie wykonać
metodę. W takim przypadku trzeba będzie edytować kod,
który korzysta z danej klasy, a to jest czasochłonne i nie-
bezpieczne.
Na szczęście w Pythonie możemy się od tego odciąć
poprzez
właściwości
, czyli specjalne pola, które tak na-
prawdę są metodkami wywołanymi za naszymi plecami.
Przykład widzimy w Listingu 3. Za pomocą specjalnej kon-
strukcji nazywanej dekoratorem, którą poprzedzamy defi-
nicję metody, oznaczamy ją jako właściwość, czyli metod-
kę przebraną za pole. Jak widać, można nawet definiować
grupy metod, które umożliwiają nadawanie takim "polom"
nowych wartości.
Morał z tej historii jest taki, że należy korzystać, kiedy
się tylko da, z tradycyjnych pól. W razie potrzeby moż-
na je zamienić właściwościami, co ma tę dodatkową za-
letę, że sposób korzystania z takiej klasy pozostaje cały
czas prosty.
Przypisy
[1] Właściwie konstrukcją obiektu zajmuje się inna metoda
_ _ new _ _
, a metoda
_ _ init _ _
pozwala jedynie
logicznie zainicjalizować dany obiekt. Jest to jednak za-
awansowane zagadnienie i dla większości potrzeb moż-
na myśleć o
_ _ init _ _
jako o konstruktorze obiek-
tów danej klasy.
[2] Jednym z takich ograniczeń jest brak dostępu do funkcji
super()
.
[3] O tym, jaka to konkretnie klasa, deiniuje zasada na-
zywająca się MRO (ang.
Method Resolution Order
).
Jest to zaawansowany temat, dla ciekawskich:
http://
www.enterthefoo.com/static/prez/mro/index.html
lub
http:
//www.python.org/download/releases/2.3/mro/
.
W następnym odcinku
W następnym miesiącu wykorzystamy wiedzę, którą zgro-
madziliśmy do operacji na plikach i przetwarzania tekstu.
Do zobaczenia za miesiąc!
ŁUKASZ LANGA
programuje w Pythonie od 8 lat, aktualnie współpracuje z STX
Next, rozwijając oprogramowanie dla sektora bankowego.
Prywatnie miłośnik muzyki fortepianowej, początkujący oj-
ciec i mąż. Adres e-mail autora: lukasz@langa.pl.
56
9/2010
Plik z chomika:
andrzej12543
Inne pliki z tego folderu:
kurs-pythona-czesc-ii-software-developers-journal.pdf
(941 KB)
kurs-pythona-czesc-i-software-developers-journal.pdf
(759 KB)
duplikaty.py
(1 KB)
Kurs Pythona, odcinek 4 Pliki i tekst.mht
(38 KB)
kurs-pythona-czesc-iii-software-developers-journal.pdf
(383 KB)
Inne foldery tego chomika:
Język C
Język C++
Język Java
Język Pascal
Język PHP
Zgłoś jeśli
naruszono regulamin