2010.05_Python 3 ...czyli co nowego w trzeciej edycji języka_[Python].pdf

(499 KB) Pobierz
441733765 UNPDF
Programowanie
Python 3
...czyli co nowego w trzeciej edycji języka
Łukasz przeprowadzi Cię przez nowości w najświeższej edycji języka
programowania Python i pokaże, w jaki sposób wpływają na sposób
tworzenia programów.
Dowiesz się:
• Dlaczego nowa wersja języka programowa-
nia Python odważnie zrywa z przeszłością,
jakie nowe rozwiązania proponuje i co to
oznacza dla zwykłego programisty.
Powinieneś wiedzieć:
• Czym jest język Python i znać przynajmniej
podstawy programowania w wersji drugiej.
Przyda się znajomość sposobu interakcji z
interpreterem w celu zrozumienia przykła-
dów kodu.
mego problemu jest w sprzeczności z pod-
stawową filozofią Pythona. Co więcej, taka
sytuacja może być groźna, ponieważ niejed-
nokrotnie zupełnie nowy kod pisany przez
początkujących programistów, bezwiednie
powiela złe szablony programistyczne, któ-
re od dawna są niewspierane.
Poziom
trudności
strukcji językowych (m.in. wyjątki i modu-
ły). Musiało jednak minąć wiele czasu, za-
nim Python zaczął wspierać programowa-
nie funkcyjne, unikod, obsługę pakietów,
zbieranie nieużytków (ang. garbage collec-
tion) czy wiele innych dzisiaj przyjmowa-
nych za oczywiste cech języka. Przykłado-
wo, metody na typie string pojawiły się
dopiero w wersji 2.0, iteratory i generatory
w wersji 2.2. Do tej wersji zresztą istniało
rozróżnienie na typy danych implemento-
wane na poziomie języka C oraz typy dane
komponowane w języku Python. Jedne ty-
py miały bardzo ograniczoną możliwość in-
terakcji z drugimi poprzez typowo obiekto-
we konstrukcje takie jak dziedziczenie czy
polimorfizm.
Wraz z ewolucją języka i biblioteki stan-
dardowej, niektóre z rozwiązań stosowa-
nych w starszych programach uznawano
z czasem za chybione, czy to z powodu czy-
telności, wydajności, ograniczonej elastycz-
ności czy wręcz po prostu błędnego działa-
nia. W tym samym czasie, z roku na rok,
Python stawał się coraz bardziej popular-
ną platformą, na której budowane były sys-
temy wielkiej skali. Ta popularność stała się
dla języka przekleństwem, ponieważ w ce-
lu zachowania zgodności wstecz z istnieją-
cymi programami, język musiał nadal ob-
sługiwać nawet najbardziej przestarzałe
rozwiązania. Taka sytuacja jest o tyle nie-
ciekawa, iż dostępność wielu równorzęd-
nych możliwości oprogramowania tego sa-
T-1000, Blues Brothers 2000,
Python 3000
W społeczności programistów Pythona krą-
żył żart, że zmiany konieczne do uporząd-
kowania języka zostaną w końcu zaimple-
mentowane w przyszłej wersji 3000. Po-
dobny do Terminatora T-1000 z płynnego
metalu, mityczny, idealny Python 3000 po-
jawiał się na listach dyskusyjnych tak czę-
sto, że przyjęła się nawet skrócona wersja
nazwy: Py3K. Ostatecznie w roku 2006
Guido van Rossum zaskoczył społeczność
stwierdzeniem, że planuje realną imple-
mentację Pythona 3000 i wydanie go jako
wersji 3.0. Z olbrzymiego worka z życzenia-
mi dla Pythona 3000 wybrano spójny ze-
staw zmian i zaczął się żmudny proces im-
plementacji. Ostatecznie, 3 grudnia 2008
roku wersja 3.0 ujrzała światło dzienne.
Zmiany w Pythonie 3.0 są z jednej strony
fundamentalne, z drugiej jednak to nadal
w gruncie rzeczy ten sam doskonały język
programowania. Różnice dotyczą głównie
pozbycia się zaszłości historycznych, naj-
częściej takich, gdzie domyślne zachowa-
nie języka nie było intuicyjne i jego nowi
użytkownicy produkowali w konsekwencji
suboptymalny kod. Przyjrzyjmy się po ko-
lei najważniejszym zmianom wprowadzo-
nym w wersji trzeciej.
sja trzecia języka Python jest
przedmiotem wielu kontrower-
sji. W społeczności programistów wytwo-
rzyło się sporo mitów i obaw związanych
z niekompatybilnością wstecz tej wer-
sji z linią 2.x. W tym artykule pokażemy,
że nie taki diabeł straszny, jak go malują,
a stopniowe otwieranie się na wersję trze-
cią niesie za sobą sporo wymiernych korzy-
ści. Nawet jeżeli nie planujesz w najbliż-
szej przeszłości przesiadać się na nową edy-
cję Pythona, znajomość nowinek jest przy-
datna, bo spora część z nich trafia również
do edycji 2.x.
Trudna droga do zen
Historia rozwoju języka Python sięga póź-
nych lat osiemdziesiątych, kiedy Guido
van Rossum rozpoczął implementację na-
stępcy języka ABC działającą pod rozpro-
szonym systemem operacyjnym Amoeba.
Od tego czasu funkcjonalność po funk-
cjonalności, możliwości języka rosły. Już
pierwsza opublikowana wersja 0.9 posiada-
ła wiele rozpoznawalnych do dzisiaj struk-
tur danych (m.in. listy i słowniki) oraz kon-
Bajty lub znaki
Python 3.0 wprowadza rozróżnienie da-
nych, na których operuje program, na dwa
rodzaje: dane binarne i dane znakowe. Te
40
05/2010
D ostępna od jakiegoś czasu wer-
441733765.038.png 441733765.039.png 441733765.040.png 441733765.041.png 441733765.001.png 441733765.002.png 441733765.003.png 441733765.004.png 441733765.005.png 441733765.006.png
Python 3
pierwsze to tablice bajtów (typ bytes ), któ-
rych treść może być dowolna, dlatego in-
terpreter nie pozwala na traktowanie da-
nych w nich zawartych jako tekst. Takie da-
ne mogą być odczytywane z plików, trans-
mitowane przez sieć itd. Drugi rodzaj da-
nych natomiast to abstrakcyjny tekst (typ
str ) przechowujący znaki: interpreter nie
pozwala na transmisję takiego tekstu przez
sieć lub do pliku bez uprzedniego okre-
ślenia, z jakiego kodowania znaków nale-
ży przy tej operacji skorzystać. Jawna kon-
wersja między ciągami bajtów a łańcucha-
mi tekstowymi jest doskonałym pomysłem,
ponieważ pozwala wydzielić zadania zwią-
zane z przetwarzaniem tekstu od zadań
związanych z transmisją lub przechowa-
niem danych.
Przy okazji przedstawiania różnicy
w traktowaniu tekstu i danych między wer-
sjami 2 i 3 często zwraca się dużą uwagę na
fakt, że wszystkie łańcuchy znaków w wer-
sji trzeciej to Unicode. W praktyce podczas
korzystania z tekstu w Pythonie 3 bardzo
rzadko trzeba myśleć o Unikodzie. Moż-
na po prostu założyć, że Python 3 operu-
je na abstrakcyjnym tekście, który może
przechować praktycznie nieograniczony
zestaw znaków [1]. Dopóki operujemy na
takim tekście w ramach programu, nie ma
dla nas znaczenia jego reprezentacja binar-
na (Listing 1).
Dopiero w momencie, kiedy zapisujemy
taki tekst na dysku lub przesyłamy przez
sieć, należy nadać mu odpowiednie kodo-
wanie znaków (Listing 2).
Podobnie, przy odczycie nowego tekstu
z dysku Python musi wiedzieć, w jakim ko-
dowaniu znaków ten tekst jest przechowy-
wany (Listing 3).
W celu ułatwienia pracy programisty do-
dano nowy tryb dostępu do plików: tryb
tekstowy. W trybie tym konwersja z typu
bytes na pythonowy str odbywa się w mo-
mencie odczytu z dysku, odczytywanie
więc odbywa się znak po znaku (a nie bajt
po bajcie) (Listing 4).
Jak widać na powyższym przykładzie,
odczytując plik w trybie tekstowym Py-
thon 3 za naszymi plecami buforuje zawsze
odpowiednią ilość bajtów, aby odczytać peł-
ne znaki. Twórcy Pythona 3 poszli jednak
jeszcze o krok dalej i zauważyli, że odczyt
plików w programach pythonowych naj-
częściej odbywa się właśnie w trybie teksto-
wym, a najpopularniejszym kodowaniem
znaków jest UTF-8. Stąd domyślne otwar-
cie pliku w trybie "r" bez jawnego poda-
nia typu danych ( "rb" lub "rt" ) spowoduje
otwarcie w trybie tekstowym. Jeżeli progra-
mista pominie deklarację kodowania zna-
ków w tak otwieranym pliku, Python 3 za-
kłada UTF-8:
Listing 1. Obsługa tekstu międzynarodowego
>>> names = []
>>> irst_name = "łukasz"
>>> names . append ( irst_name [ 0 ] . upper () + irst_name [ 1 :])
>>> names
[ 'Łukasz' ]
>>> names . append ( "René" )
>>> names . append ( "Krüger" )
>>> text = " " . join ( names )
>>> text
'Łukasz René Krüger'
Listing 2. Kodowanie tekstu w celu transmisji danych
names_ile = open ( "/tmp/names" , "wb" )
>>> names_ile . write ( text )
Traceback ( most recent call last ):
File "<stdin>" , line 1 , in < module >
TypeError : must be bytes or buffer , not str
>>> encoded_text = text . encode ( "utf-8" )
>>> encoded_text
b '\xc5\x81ukasz Ren\xc3\xa9 Kr\xc3\xbcger'
>>> names_ile . write ( encoded_text )
21
>>> names_ile . close ()
Listing 3. Wczytanie tekstu z postaci binarnej
>>> names_ile = open ( "/tmp/names" , "rb" )
>>> byte_content = names_ile . read ()
>>> byte_content
b '\xc5\x81ukasz Ren\xc3\xa9 Kr\xc3\xbcger'
>>> byte_content . decode ( "utf-8" )
'Łukasz René Krüger'
Listing 4. Odczyt pliku w trybie binarnym i tekstowym
>>> byte_ile = open ( "/tmp/names" , "rb" )
>>> byte1 = byte_ile . read ( 1 )
>>> byte1
b '\xc5'
>>> byte1 . decode ( "utf-8" )
Traceback ( most recent call last ):
File "<stdin>" , line 1 , in < module >
UnicodeDecodeError : 'utf8' codec can 't decode byte 0xc5 in position 0: unexpected
end of data
>>> text_ile = open("/tmp/names", "rt", encoding="utf-8")
>>> char1 = text_ile.read(1)
>>> char1
' Ł '
>>> char1.encode("utf-8")
b' \ xc5 \ x81 '
Listing 5. Dostęp do indeksów sekwencji i atrybutów obiektów w formatowaniu
>>> 'Pierwszy element: {keys[0]:>10s}' . format ( keys = sorted ( sys . modules . keys ()))
'Pierwszy element: __main__'
>>> f = open ( '/tmp/names' , 'r' )
>>> 'Kodowanie pliku {f.name}: {f.encoding}' . format ( f = f )
'Kodowanie pliku /tmp/names: UTF-8'
www.sdjournal.org
41
441733765.007.png 441733765.008.png 441733765.009.png 441733765.010.png 441733765.011.png 441733765.012.png 441733765.013.png 441733765.014.png 441733765.015.png 441733765.016.png 441733765.017.png
Programowanie
>>> text_ile = open("/tmp/names", "r")
>>> text_ile.encoding
'UTF-8'
>>> text_ile.readline()
'Łukasz René Krüger'
Jak widać, każda z implementacji wbu-
dowanych funkcji w danym typie służy
do czegoś innego. Ta ostatnia, ze względu
na swoją konfigurowalność poprzez argu-
ment, jest szczególnie przydatna w prze-
twarzaniu tekstu. Do tego celu można
używać zarówno wbudowanej funkcji
format() , jak i nowej metody format() na
łańcuchach znaków:
Kolejną dużą zmianą w przetwarza-
niu tekstu jest przekształcenie wyrażenia
print w funkcję. Pozwala to z jednej stro-
ny na bardziej spójny kod, gdzie składnia
print nie jest wyjątkiem. Z drugiej stro-
ny pozwala na podmianę implementacji
funkcji print() inną w trakcie wykona-
nia programu, dzięki czemu można w bar-
dziej elegancki sposób obsługiwać ko-
munikaty diagnostyczne. Kilka przykła-
dów możliwości nowej funkcji print (Li-
sting 6).
Przetwarzanie tekstu
Rozumiejąc już różnicę między tekstem
a danymi binarnymi w wersji trzeciej Pytho-
na, skupmy się chwilowo na samym tekście i
nowych cechach w jego przetwarzaniu. Du-
żą rolę w trakcie operacji na tekście ma moż-
liwość wstrzykiwania w łańcuchy teksto-
we danych zewnętrznych, po odpowiednim
sformatowaniu. Funkcjonalność tę zapo-
czątkowała funkcja printf w języku C i do
czasu Pythona 3 niewiele się w tej kwestii
zmieniło. Klasyczna notacja jest nadal do-
stępna, ale w przyszłości zostanie ostatecz-
nie usunięta z języka. W jej miejsce wprowa-
dzono nowy mechanizm, o znacznie zwięk-
szonej elastyczności: format() . Podstawo-
wą różnicą w stosunku do tradycyjnego jest
fakt, że obiekt formatowany sam definiuje,
w jaki sposób jego formatowanie przebiega:
>>> format(x, "6.1f")
' 0.1'
>>> format(x, "<6.1f")
'0.1 '
>>> '{0:6.1f}, {0:<6.1f}'.format(x)
' 0.1, 0.1 '
Najlepsza rzecz od odkrycia
krojonego chleba: iteracja
Od czasu wprowadzenia do języka genera-
torów i iteracji, podejście do rozwiązywa-
nia wielu problemów obliczeniowych dia-
metralnie się zmieniło. Możliwość opisy-
wania problemu, jak gdyby był wykonywa-
ny sekwencyjnie, powoduje z jednej stro-
ny dużą czytelność, a z drugiej brak na-
rzutu pamięciowego i wydajnościowego na
uprzednie przygotowanie struktur danych.
To, co w wersji drugiej Pythona wymagało
stosowania metod z przedrostkiem iter lub
x, w Pythonie 3 jest zachowaniem domyśl-
nym (Listing 7).
Zmiana ta jest o tyle istotna, że teraz za-
chowanie naturalne - domyślne, jest zacho-
waniem generującym algorytmy o znacznie
lepszej charakterystyce pamięciowej i wy-
dajnościowej. Jeżeli jednak nasz konkretny
algorytm będzie wymagał klasycznej listy,
możemy ją nadal uzyskać za pomocą jaw-
nej konwersji:
Metoda format() z ostatniego przykła-
du korzysta z nowej notacji {indeks _
argumentu:sposób _ formatowania} .
W powyższym przykładzie dwukrotnie
wykorzystano argument o indeksie ze-
rowym podany do metody format() , za
każdym razem formatując go inaczej. In-
deksowanie jest jednak bardzo elastycz-
ne i nie ogranicza się do prostego podawa-
nia numeru argumentu funkcji format() .
Możliwe jest również odwoływanie się do
konkretnych indeksów w kolekcjach lub
wręcz atrybutów obiektów (Listing 5).
Sposób formatowania jest opisywany
w sposób bardzo zbliżony do tradycyjnego,
możliwe wartości opisuje Tabela 1.
>>> x = 0.3/3
>>> x.__str__()
'0.1'
>>> x.__repr__()
'0.09999999999999999'
>>> x.__format__("0.2f")
'0.10'
Tabela 1. Zapis łańcuchów formatujących w Python 3
Rodzaj Wartość Znaczenie
Wyrównanie <
wyrównanie do lewej
>>> modules_keys = list(sys.modules.keys())
>>> modules_keys.sort()
>>> modules_keys[:3]
['__main__', '_abcoll', '_bisect']
^
wyrównanie do środka
>
wyrównanie do prawej
Szerokość liczba
ilość znaków, które zajmie całe pole
Dokładność liczba
dla zmiennych typu int i loat , ilość miejsc po przecinku
Cukierki składniowe
Tzw. syntactic sugar to cechy języka bez
istotnego wkładu funkcjonalnego, które
jednak pozwalają w lepszy sposób wyrażać
zamiary programisty. Najczęściej cukierki
takie cechuje zwięzłość i czytelność. W kul-
turze programistów Pythona cechy te są
szczególnie pożądane, nic więc dziwnego,
że wersja trzecia przyniosła kilka nowych.
Najciekawsze wydaje się składanie słowni-
ków i zbiorów (ang. odpowiednio dictiona-
ry comprehensions, set comprehensions),
przykładowo (Listing 8).
Ciekawa wydaje się też możliwość ano-
towania funkcji i metod. Język sam w so-
bie nie interpretuje tych anotacji, ale są
dostępne w czasie uruchomienia do intro-
spekcji. Taka konstrukcja może posłużyć do
eleganckiego implementowania różnego ro-
dzaju kontroli typów, interfejsów lub doku-
mentowania kodu (Listing 9).
Kod d
formatowanie dziesiętnej liczby całkowitej
f
formatowanie dziesiętnej liczby zmiennoprzecinkowej
s
formatowanie łańcucha znaków
e
formatowanie liczby w notacji naukowej
x
formatowanie liczby szesnastkowej
o
formatowanie liczby ósemkowej
b
formatowanie liczby binarnej
%
formatowanie liczby w procentach ( 1.0 == 100% )
Tabela 2. Reorganizacja bibliotek HTTP
Python 2.x
Python 3
httplib
http.client
BaseHTTPServer
http.server
CGIHTTPServer
http.server
SimpleHTTPServer
http.server
Cookie
http.cookies
cookielib
http.cookiejar
42
05/2010
441733765.018.png 441733765.019.png 441733765.020.png 441733765.021.png 441733765.022.png 441733765.023.png 441733765.024.png
 
Python 3
Biblioteka standardowa
Python 3.0 posiada w pełni zrewidowaną
bibliotekę standardową. Usunięto z niej
wiele nieutrzymywanych bibliotek, zlikwi-
dowano też biblioteki o powtarzającej się
funkcjonalności lub rzadko wykorzystywa-
ne. Pełną listę można znaleźć pod adresem
[2]. Struktura pozostałych bibliotek zosta-
ła przeorganizowana tak, aby lepiej odpo-
wiadała logicznie funkcjonalności zawar-
tej w danej bibliotece. Ponadto, nazewnic-
two bibliotek zostało dostosowane do ofi-
cjalnych reguł stylu [3]. Przykład zmian dla
pakietów odpowiedzialnych za komunika-
cję HTTP przedstawia Tabela 2.
krotek w listach argumentów def fun(a,
(b, c)) , usunięto notację `var` na rzecz
repr(var) ). Ponadto wynikiem dzielenia
jest teraz zawsze liczba zmiennoprzecin-
kowa, a niejawne importy zależne są nie-
dozwolone.
Zmiany dotknęły też samą definicję klas,
która teraz wspiera dynamiczne podawa-
nie klas bazowych, zmienia określanie me-
taklas oraz pozwala dołączać dowolne ar-
gumenty kluczowe do definicji klas (Li-
sting 10).
Listing 6. Nowa funkcja print w działaniu
>>> print ( 'Hello' , 'World' )
Hello World
>>> print ( 'Hello' , 'World' , end = '!\n\n' )
Hello World !
>>> print ( 1 , 2 , 3 , sep = '; ' )
1 ; 2 ; 3
>>> print ( 'Error message!' , ile = sys . stderr )
Error message !
Zmiany występujące
również w Pythonie 2.6
Szereg oryginalnych zmian z Pythona 3.0
pojawiło się również w wersji 2.6. W po-
dobny sposób wersja 2.7 będzie poszerzo-
na o część nowych cech wersji 3.1 i nad-
chodzącej 3.2. Takie przenoszenie wstecz
nowych funkcjonalności ma na celu uła-
twienie późniejszej aktualizacji progra-
mów do wersji trzeciej języka. Użytkow-
ników Pythona, którzy nie śledzą na bieżą-
co zmian w kolejnych jego odsłonach, mo-
że zaskoczyć, że następujące funkcjonalno-
ści są dostępne zarówno w wersji 3.0, jak
i w 2.6:
Listing 7. Domyślne wykorzystanie iteratorów w Pythonie 3
>>> for i in range ( 10 ):
... print ( i , end = ' ' )
... if i == 9 : print ()
...
0 1 2 3 4 5 6 7 8 9
>>> type ( range ( 10 ))
< class 'range' >
>>> isinstance ( range ( 10 ) , list )
False
>>> import sys
>>> type ( sys . modules )
< class 'dict' >
>>> type ( sys . modules . keys ())
< class 'dict_keys' >
>>> for i in sys . modules . keys ():
... if i [ 0 ] == '_' :
... print ( i , end = ' ' )
...
_collections _sre __main__ _heapq _weakref _codecs _bisect _functools _locale _io
_weakrefset _abcoll
• wyrażenie with , uogólniające zarzą-
dzanie kontekstowe zasobami (np. pli-
kami) [5]
• pakiet multiprocessing , pozwalają-
cy implementować aplikacje równole-
głe wykorzystujące osobne procesy za-
miast wątków [6]
• dekoratory klas [7]
• nowa składnia obsługi wyjątków:
except Error as varError2 as var2
• usunięte zostało rzucanie łańcuchów
znaków jako wyjątków (zaszłość z wer-
sji 0.9!)
Listing 8. Składanie słowników i zbiorów
Oprócz wymienionych wyżej i kilku
mniej istotnych, Python 2.6 zawiera rów-
nież opisane w poprzednich sekcjach no-
we formatowanie łańcuchów, nową funk-
cję print czy też nową bibliotekę io .
>>> some_dict = { 'a' : 1 , 'b' : 2 , 'c' : 3 , 'd' : 3 , 'e' : 3 }
>>> inverted = { v : k for k , v in some_dict . items () }
>>> inverted
{ 1 : 'a' , 2 : 'b' , 3 : 'd' }
>>> some_set = { value / 2 for value in some_dict . values () }
>>> some_set
{ 0.5 , 1.5 , 1.0 }
>>> other_set = { 1 , 3 , 5 }
Zmiany usuwające
przestarzałe cechy języka
W wersji 3.0 na dobre usunięto wiele roz-
wiązań, które od dawna były uznawane
przez całe środowisko za przestarzałe i pro-
blematyczne. Na pierwszy ogień poszły kla-
sy starego typu, czyli rodzaj klas stworzony
przed zunifikowaniem typów C i typów py-
thonowych. Wraz z nimi dokonano porząd-
ków w składni języka (m.in. zrezygnowano
ze znaku nierówności <> , rozpakowywania
Listing 9. Anotacje
>>> def fun ( a : "non-empty" , b : "positive integer" ) -> "string" :
... pass
...
>>> fun . __annotations__
{ 'a' : 'non-empty' , 'b' : 'positive integer' , 'return' : 'string' }
www.sdjournal.org
43
441733765.025.png 441733765.026.png 441733765.027.png 441733765.028.png 441733765.029.png 441733765.030.png 441733765.031.png 441733765.032.png 441733765.033.png 441733765.034.png 441733765.035.png
Programowanie
3000 niezgodności
Ze względu na rozmach zmian w inter-
preterze i bibliotece standardowej, progra-
my tworzone z myślą o Pythonie 2.x nie
są zgodne z nową wersją. Takie założenie
twórców stanowi jednak nie lada wyzwa-
nie dla programistów, ponieważ w prakty-
ce nawet najprostszy program pisany z my-
ślą o wersji 2.x nie uruchomi się pod wersją
3.x bez zmian w kodzie. W konsekwencji
większość istniejących bibliotek zewnętrz-
nych na dzień dzisiejszy nie wspiera jesz-
cze nowej edycji Pythona. Na szczęście ilość
kompatybilnych pakietów rośnie, nadal jed-
nak bardzo łatwo trafić na bibliotekę, bez
której nie wyobrażamy sobie życia, a która
nie działa pod "trójką". Wspomnieć można
choćby o takich gigantach jak Python Ima-
ging Library, virtualenv, easy_install [8] czy
WSGI. Z czasem jednak przybywa uaktual-
nionych pakietów, ostatnio przeportowane
zostały biblioteki Jinja2 i lxml. Część biblio-
tek zawiera wersje kompatybilne w repozy-
toriach kodu źródłowego i można liczyć na
to, że w niedalekiej przyszłości ujrzą światło
dzienne na PyPI [9].
Co więc robić? Czekać dalej, aż masa kry-
tyczna zostanie przekroczona? Właśnie ta-
kie oczekiwanie powoduje, że przejście
z wersji 2.x do 3.x zajmuje tak długo. Każ-
dy większy projekt pisany w oparciu o Py-
thona ma z pewnością wydzielone bibliote-
ki, które da się przeportować, bo nie są bez-
pośrednio zależne od nieistniejących kom-
ponentów. Utrzymywanie dla nich wersji
zgodnej z Pythonem 3 jest o tyle mądre, iż
w momencie, kiedy giganci środowiska py-
thonowego wydadzą wersje zgodne z Py-
thonem 3, nasze projekty będą gotowe na
migrację. PyQt już działa, portowane są fra-
meworki Django i Pylons. W dalszej per-
spektywie ujrzymy też ZOPE i Twisted.
Jak portować? Nie jest to na szczęście
takie trudne, jakby się mogło wydawać.
W dystrybucji Pythona 3 zawarte jest na-
rzędzie 2to3 [10], które dużą część pracy
wykonuje automatycznie za programistę.
Kiedy narzędzie to trafia na odpowiednio
dostosowany kod 2.x, potrafi wyproduko-
wać w pełni działającą wersję dla Pythona
3. Nie zawsze jest tak łatwo, niemniej jed-
nak warto spróbować. Portowanie za pomo-
2to3 działa szczególnie dobrze dla bi-
bliotek operujących na tekście, w odróżnie-
niu od takich, które operują na danych bi-
narnych. Dodatkowo, możliwe jest dystry-
buowanie pakietów źródłowych opartych
o distribute , które w przypadku wykrycia
wersji trzeciej Pythona automatycznie wy-
konają konwersję przy użyciu 2to3 . Ozna-
cza to, że możemy przygotować pakiety
w PyPI, które będą poprawne zarówno dla
wersji drugiej jak i trzeciej. Jedyną wadą ta-
kiego rozwiązania jest fakt, że kod źródło-
wy pozwalający na bezbłędną pracę zarów-
no w interpreterze w wersji 2 jak i w wersji
najnowszej, nie jest tak ładny jak może być
kod pisany z myślą o tylko jednej gałęzi.
Listing 10. Argumenty kluczowe w de�nicji klas
>>> class A : pass
>>> class B : pass
>>> bases = A , B
>>> class C (* bases ): pass
>>> C . __bases__
(< class '__main__.A' > , < class '__main__.B' >)
>>> class Meta ( type ):
... def __new__ ( cls , name , bases , cls_dict , message ):
... print ( 'new' , message )
... return type . __new__ ( cls , name , bases , cls_dict )
... def __init__ ( cls , name , bases , cls_dict , message ):
... print ( 'init' , message )
... super () . __init__ ( name , bases , cls_dict )
...
>>> class D ( metaclass = Meta , message = "This is D" ): pass
new This is D
init This is D
>>> D ()
< __main__ . D object at 0x100667f10 >
>>> class E ( metaclass = Meta , message = "This is E" ): pass
new This is E
init This is E
Przypisy
Podsumowanie
W ostatecznym rozrachunku wersja 3 Py-
thona jest dużym krokiem naprzód. Wpro-
wadzenie szeregu niezgodnych wstecz mo-
dyfikacji do języka i biblioteki standardo-
wej było dla twórców posunięciem ryzy-
kownym, ponieważ biorąc pod uwagę popu-
larność języka i mnogość bibliotek zewnę-
trnzych, niebagatelnie utrudnia migrację
na wersję najnowszą. Jednocześnie jednak
zmiany te porządkują język i umożliwiają je-
go dalszy rozwój.
• [1] Jest to pewne uproszczenie, Unicode posiada kilka możliwych reprezentacji binar-
nych, spośród których Python może wewnętrznie wykorzystywać dwie: UCS-2 i UCS-4.
Ta pierwsza posiada alfabet ograniczony do 65536 podstawowych symboli, ta druga po-
zwala na reprezentację pełnego alfabetu Unicode, wymaga natomiast dwukrotnie więk-
szej ilości bitów na przechowanie takiego samego ciągu znaków. Zmiana sposobu kodo-
wania znaków Unicode jest możliwa na etapie kompilacji interpretera, domyślnie używa-
ny jest bardziej popularny zestaw UCS-2.
• [2] http://www.python.org/dev/peps/pep-3108/
• [3] http://www.python.org/dev/peps/pep-0008/
• [4] Oczywiście bardziej złożone aplikacje zdecydowanie zyskają, korzystając z biblioteki
logging, która daje znacznie większą konigurowalność.
• [5] http://www.python.org/dev/peps/pep-0343/
• [6] http://www.python.org/dev/peps/pep-0371/
• [7] http://www.python.org/dev/peps/pep-3129/
• [8] Istnieje ambitny projekt porządkujący kwestię paczkowania oprogramowania pytho-
nowego: distribute ( http://python-distribute.org/ ). Ze względu na to, że odchodzi on od
koncepcji paczek egg, nie implementuje on funkcjonalności easy_install. Zostanie ona
zastąpiona przez PIP ( http://pip.openplans.org/ ), który posiada wersję zgodną z Pytho-
nem 3 w repozytorium.
• [9] Python Package Index: http://pypi.python.org/pypi
• [10] http://docs.python.org/library/2to3.html
ŁUKASZ LANGA
Autor interesuje się muzyką, reżyserią dźwię-
ku i fotogra�ą, sprawdza się jako młody tata,
a w wolnym czasie prowadzi własną �rmę progra-
mistyczną. Kontakt z autorem: lukasz@langa.pl
44
05/2010
441733765.036.png 441733765.037.png
 
Zgłoś jeśli naruszono regulamin