Nacházíte se zde: Domů ‣ Ponořme se do Pythonu 3 ‣
Úroveň obtížnosti: ♦♦♦♦♦
2to3
❝ Life is pleasant. Death is peaceful. It’s the transition that’s troublesome. ❞
(Život je zábavný. Smrt je klidná. Nepříjemný je ten přechod.)
— Isaac Asimov (připsáno)
Mezi Pythonem 2 a Pythonem 3 se toho změnilo tolik, že najdete jen mizivé procento programů, které bez úprav běží v obou verzích. Ale nepropadejte zoufalství! K usnadnění přechodu se Python 3 dodává s pomocným skriptem nazvaným 2to3
. Když mu předáte svůj zdrojový soubor napsaný pro Python 2 jako vstup, převede automaticky do podoby pro Python 3 vše, co dovede. Případová studie: Přepis chardet
pro Python 3 popisuje, jak se skript 2to3
spouští. Ukazuje také věci, které se automaticky neopraví. V této příloze najdete dokumentaci toho, co dovede opravit automaticky.
print
V Pythonu 2 byl print
příkazem. Pokud jsme cokoliv chtěli vytisknout, jednoduše jsme to připsali za klíčové slovo print
. V Pythonu 3 je print()
funkcí. Pokud chceme cokoliv vytisknout, předáme to funkci print()
stejně jako každé jiné funkci.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | print
| print()
|
② | print 1
| print(1)
|
③ | print 1, 2
| print(1, 2)
|
④ | print 1, 2,
| print(1, 2, end=' ')
|
⑤ | print >>sys.stderr, 1, 2, 3
| print(1, 2, 3, file=sys.stderr)
|
print()
bez zadání argumentů.
print()
s jedním argumentem.
print()
s dvěma argumenty.
print
čárkou, vytiskly se hodnoty oddělené mezerou, pak se vytiskla ještě jedna koncová mezera a tisk skončil bez generování přechodu na nový řádek. (Z technického hlediska je to o něco komplikovanější. Příkaz print
v Pythonu 2 používal nyní již nežádoucí (deprecated) atribut zvaný softspace. Místo skutečného tisku mezery nastavil Python 2 sys.stdout.softspace
na 1. Znak mezery ve skutečnosti nebyl vytištěn, dokud se nemělo na stejný řádek tisknout něco dalšího. Pokud další příkaz print
tiskl přechod na nový řádek, byl atribut sys.stdout.softspace
nastaven na 0 a mezera se nikdy nevytiskla. Tohoto rozdílu byste si pravděpodobně nikdy nevšimli, pokud by vaše aplikace nebyla citlivá na přítomnost nebo nepřítomnost koncových bílých znaků ve výstupu, který byl vygenerován příkazem print
.) V Pythonu 3 dosáhneme stejného efektu tím, že funkci print()
předáme pojmenovaný argument s hodnotou end=' '
. Výchozí hodnotou argumentu end
je '\n'
(přechod na nový řádek), takže po vytisknutí ostatních argumentů jeho přepsáním potlačíme přechod na nový řádek.
sys.stderr
— uvedením zápisu >>jméno_roury
. V Pythonu 3 dosáhneme stejného efektu předáním odkazu na rouru pojmenovaným argumentem file
. Výchozí hodnotou argumentu file
je sys.stdout
(standardní výstup), takže přepsáním této hodnoty dosáhneme přesměrování do jiné roury.
Python 2 pracoval s dvěma typy řetězců: s Unicode řetězci a s ne-Unicode řetězci. Python 3 podporuje jediný řetězcový typ: Unicode řetězce.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | u'PapayaWhip'
| 'PapayaWhip'
|
② | ur'PapayaWhip\foo'
| r'PapayaWhip\foo'
|
unicode()
V Pythonu 2 se pro převod objektů na řetězec používaly dvě globální funkce: unicode()
pro převod na Unicode řetězce a str()
pro převod na ne-Unicode řetězce. Python 3 má jediný řetězcový typ, Unicode řetězce, takže vše, co potřebujeme, je funkce str()
. (Funkce unicode()
už neexistuje.)
Poznámky | Python 2 | Python 3 |
---|---|---|
unicode(cokoliv)
| str(cokoliv)
|
long
Python 2 používal pro celá čísla dva datové typy: int
a long
. Hodnota typu int
nemohla být větší než konstanta sys.maxint
, která byla závislá na platformě. „Dlouhá“ čísla byla definována přidáním L
na konec čísla a mohla nabývat větších hodnot než čísla typu int
. V Pythonu 3 je jen jeden celočíselný typ, který se jmenuje int
a většinou se chová jako typ long
v Pythonu 2. Protože už neexistují dva typy, nemusí se používat speciální syntaxe pro jejich rozlišení.
Přečtěte si: PEP 237: Unifying Long Integers and Integers.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | x = 1000000000000L
| x = 1000000000000
|
② | x = 0xFFFFFFFFFFFFL
| x = 0xFFFFFFFFFFFF
|
③ | long(x)
| int(x)
|
④ | type(x) is long
| type(x) is int
|
⑤ | isinstance(x, long)
| isinstance(x, int)
|
long()
, protože přestal existovat typ long (dlouhý integer). K převodu proměnné na celé číslo použijeme funkci int()
.
int
(nikoliv s long
).
isinstance()
. Při zjišťování, zda jde o celočíselný typ, se opět odkážeme na int
a ne na long
.
Python 2 podporoval operátor <>
jako synonymum pro !=
(porovnání na různost). Python 3 podporuje pouze operátor !=
a přestal podporovat <>
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | if x <> y:
| if x != y:
|
② | if x <> y <> z:
| if x != y != z:
|
has_key()
V Pythonu 2 používaly slovníky metodu has_key()
(doslova „má klíč“) pro testování, zda se ve slovníku nachází zadaný klíč. V Pythonu 3 tato metoda přestala existovat. Místo ní musíme používat operátor in
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | a_dictionary.has_key('PapayaWhip')
| 'PapayaWhip' in a_dictionary
|
② | a_dictionary.has_key(x) or a_dictionary.has_key(y)
| x in a_dictionary or y in a_dictionary
|
③ | a_dictionary.has_key(x or y)
| (x or y) in a_dictionary
|
④ | a_dictionary.has_key(x + y)
| (x + y) in a_dictionary
|
⑤ | x + a_dictionary.has_key(y)
| x + (y in a_dictionary)
|
in
má vyšší prioritu než operátor or
, takže podvýrazy x in a_dictionary
a y in a_dictionary
nemusíme uzavírat do závorek.
x or y
— in
má vyšší prioritu než or
. (Poznámka: Tento kód se od předchozího řádku zcela liší. Python interpretuje nejdříve x or y
. Výsledkem je buď x (pokud se x interpretuje v booleovském kontextu jako true), nebo y. Potom pro výslednou hodnotu kontroluje, zda se ve slovníku a_dictionary vyskytuje jako klíč.)
+
má vyšší prioritu než operátor in
. Z technického hlediska by tento zápis nemusel používat závorky kolem x + y
, ale 2to3
je stejně přidává.
y in a_dictionary
závorky určitě uvedeny, protože operátor +
má vyšší prioritu než operátor in
.
V Pythonu 2 mnohé slovníkové metody vracely seznamy. Mezi nejpoužívanější metody patřily keys()
, items()
a values()
. V Pythonu 3 všechny tyto metody vracejí dynamické pohledy (view). V některých situacích to nečiní žádný problém. Pokud je návratová hodnota těchto metod ihned předána jiné funkci, která iteruje přes celou posloupnost, bude jedno, zda je skutečným typem seznam nebo pohled (view). V jiném kontextu to ale může mít velký vliv. Pokud očekáváme kompletní seznam s jednotlivě adresovatelnými prvky, náš kód se zakucká, protože pohledy nepodporují indexování (tj. zpřístupňování prvku přes index).
Poznámky | Python 2 | Python 3 |
---|---|---|
① | a_dictionary.keys()
| list(a_dictionary.keys())
|
② | a_dictionary.items()
| list(a_dictionary.items())
|
③ | a_dictionary.iterkeys()
| iter(a_dictionary.keys())
|
④ | [i for i in a_dictionary.iterkeys()]
| [i for i in a_dictionary.keys()]
|
⑤ | min(a_dictionary.keys())
| žádná změna |
2to3
se přiklání k bezpečnému řešení. Voláním funkce list()
převádí hodnotu vracenou metodou keys()
na statický seznam. Bude to fungovat vždycky, ale někdy to bude méně efektivní než použití pohledu (view). Převedený kód byste si měli prohlédnout a zvážit, zda je statický seznam nezbytně nutný, nebo zda by nestačil pohled.
items()
. Stejnou věc provede 2to3
s metodou values()
.
iterkeys()
. Použijte keys()
, a pokud je to nezbytné, udělejte z pohledu iterátor voláním funkce iter()
.
2to3
pozná, když je metoda iterkeys()
použita uvnitř generátorové notace seznamu. Převede ji na metodu keys()
(neobaluje ji ještě jedním voláním iter()
). Funguje to, protože přes pohledy (view) lze iterovat.
2to3
pozná případ, kdy je metoda keys()
předána funkci, která iteruje celou posloupností. V takovém případě se návratová hodnota nemusí konvertovat na seznam. Funkce min()
bude vesele iterovat i přes pohled. Týká se to funkcí min()
, max()
, sum()
, list()
, tuple()
, set()
, sorted()
, any()
a all()
.
Několik modulů standardní pythonovské knihovny bylo přejmenováno. Několik vzájemně souvisejících modulů bylo spojeno dohromady nebo bylo reorganizováno tak, aby byly jejich vztahy logičtější.
http
V Pythonu 3 bylo několik modulů souvisejících s HTTP spojeno do jednoho balíku nazvaného http
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | import httplib
| import http.client
|
② | import Cookie
| import http.cookies
|
③ | import cookielib
| import http.cookiejar
|
④ |
| import http.server
|
http.client
implementuje nízkoúrovňovou knihovnu, která vytváří požadavky na HTTP zdroje a interpretuje související HTTP odpovědi.
http.cookies
poskytuje pythonovské rozhraní pro cookies prohlížeče, které se posílají v HTTP hlavičce HTTP hlavička.
http.cookiejar
manipuluje se soubory na disku, které oblíbené webové prohlížeče používají k ukládání cookies.
http.server
implementuje jednoduchý HTTP server.
urllib
Python 2 obsahoval změť překrývajících se modulů pro rozklad (parse) a kódování URL a pro získávání příslušného obsahu. V Pythonu 3 byly moduly refaktorizovány a sloučeny do jednoho balíku urllib
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | import urllib
| import urllib.request, urllib.parse, urllib.error
|
② | import urllib2
| import urllib.request, urllib.error
|
③ | import urlparse
| import urllib.parse
|
④ | import robotparser
| import urllib.robotparser
|
⑤ |
|
|
⑥ |
|
|
urllib
v Pythonu 2 obsahoval řadu funkcí včetně urlopen()
pro načítání dat a splittype()
, splithost()
a splituser()
pro rozklad URL na podstatné části. Uvnitř nového balíku urllib
byly tyto funkce logičtěji přeorganizovány. Skript 2to3
také změní všechna volání těchto funkcí, aby zohlednil nové schéma pojmenování.
urllib2
z Pythonu 2 byl v Pythonu 3 vložen do balíčku urllib
. Všechny oblíbené věci z urllib2
— metoda build_opener()
, třídy Request
a HTTPBasicAuthHandler
a související věci — jsou stále k dispozici.
urllib.parse
z Pythonu 3 obsahuje všechny funkce z původního modulu urlparse
z Pythonu 2.
urllib.robotparser
zpracovává soubory robots.txt
.
FancyURLopener
, která obsluhuje HTTP přesměrování a další stavové kódy, je v novém modulu urllib.request
stále k dispozici. Funkce urlencode()
se přesunula do urllib.parse
.
Request
je v urllib.request
stále k dispozici, ale konstanty jako HTTPError
byly přesunuty do urllib.error
.
Zmínil jsem se o tom, že 2to3
přepíše také volání vašich funkcí? Pokud například v kódu pro Python 2 importujete modul urllib
a získáváte data voláním urllib.urlopen()
, skript 2to3
opraví jak příkaz import, tak volání funkce.
Poznámky | Python 2 | Python 3 |
---|---|---|
|
|
dbm
Všechny klony DBM se nyní nacházejí jediném balíku dbm
. Pokud potřebujeme použít nějakou specifickou variantu, jako například GNU DBM, můžeme importovat příslušný modul z balíku dbm
.
Poznámky | Python 2 | Python 3 |
---|---|---|
import dbm
| import dbm.ndbm
| |
import gdbm
| import dbm.gnu
| |
import dbhash
| import dbm.bsd
| |
import dumbdbm
| import dbm.dumb
| |
| import dbm
|
xmlrpc
XML-RPC je odlehčená (lightweight) metoda pro provádění RPC (vzdálené volání procedur) přes HTTP. Klientská knihovna pro XML-RPC a několik implementací XML-RPC serveru jsou nyní zkombinovány do jednoho balíčku xmlrpc
.
Poznámky | Python 2 | Python 3 |
---|---|---|
import xmlrpclib
| import xmlrpc.client
| |
| import xmlrpc.server
|
Poznámky | Python 2 | Python 3 |
---|---|---|
① |
| import io
|
② |
| import pickle
|
③ | import __builtin__
| import builtins
|
④ | import copy_reg
| import copyreg
|
⑤ | import Queue
| import queue
|
⑥ | import SocketServer
| import socketserver
|
⑦ | import ConfigParser
| import configparser
|
⑧ | import repr
| import reprlib
|
⑨ | import commands
| import subprocess
|
import cStringIO as StringIO
. Pokud operace selhala, provedl se místo toho příkaz import StringIO
. V Pythonu 3 už to nedělejte. Modul io
to udělá za vás. Nalezne nejrychlejší dostupnou implementaci a použije ji automaticky.
pickle
to udělá za vás.
builtins
obsahuje globální funkce, třídy a konstanty, které se používají napříč celým jazykem Python. Redefinicí funkce v modulu builtins
provedete redefinici globální funkce úplně všude. Je to přesně tak mocné a děsivé, jak to zní.
copyreg
přidává podporu „piklení“ pro uživatelské typy definované v C.
queue
implementuje frontu pro více producentů a více konzumentů.
socketserver
poskytuje obecné (generické) bázové třídy pro implementaci různých druhů soketových serverů.
configparser
zpracovává konfigurační soubory ve stylu INI.
reprlib
reimplementuje zabudovanou funkci repr()
s přidaným ovládáním. Lze předepsat, jak dlouhé mohou reprezentace být, než dojde k jejich ořezání.
subprocess
umožňuje vytvářet procesy, připojovat se k jejich rourám (pipe) a získávat jejich návratové kódy.
Balíček je skupina souvisejících modulů, které se používají jako celek. Pokud se v Pythonu 2 moduly uvnitř balíčku potřebovaly odkazovat jeden na druhý, používali jsme příkaz import foo
nebo from foo import Bar
. V Pythonu 2 interpret hledal foo.py
nejdříve uvnitř aktuálního balíčku a teprve potom prohledával ostatní adresáře z pythonovské vyhledávací cesty (sys.path
). Python 3 funguje trošku jinak. Místo prohledávání aktuálního balíčku začne přímo pythonovskou vyhledávací cestou. Pokud chceme, aby jeden modul uvnitř balíčku importoval jiný modul ze stejného balíčku, musíme explicitně zadat relativní cestu mezi uvedenými moduly.
Dejme tomu, že bychom měli následující balíček s více soubory ve stejném adresáři:
chardet/ | +--__init__.py | +--constants.py | +--mbcharsetprober.py | +--universaldetector.py
Teď předpokládejme, že universaldetector.py
potřebuje importovat celý soubor constants.py
a jednu třídu z mbcharsetprober.py
. Jak to vlastně uděláme?
Poznámky | Python 2 | Python 3 |
---|---|---|
① | import constants
| from . import constants
|
② | from mbcharsetprober import MultiByteCharSetProber
| from .mbcharsetprober import MultiByteCharsetProber
|
from . import
. Tečka ve skutečnosti označuje relativní cestu od tohoto souboru (universaldetector.py
) k souboru, který chceme importovat (constants.py
). V tomto případě se nacházejí ve stejném adresáři, takže použijeme jednu tečku. Importovat můžeme i z rodičovského adresáře (from .. import jinymodul
) nebo z podadresáře.
mbcharsetprober.py
nachází ve stejném adresáři jako universaldetector.py
, takže cestu vyjádříme jednou tečkou. Importovat můžeme i z rodičovského adresáře (from ..jinymodul import JinaTrida
) nebo z podadresáře.
next()
V Pythonu 2 měly iterátory metodu next()
, která vracela další položku z posloupnosti. V Pythonu 3 to stále platí, ale máme k dispozici také globální funkci next()
, která přebírá iterátor jako argument.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | anIterator.next()
| next(anIterator)
|
② | funkce_ktera_vraci_iterator().next()
| next(funkce_ktera_vraci_iterator())
|
③ |
|
|
④ |
| žádná změna |
⑤ |
|
|
next()
předáváme iterátor globální funkci next()
.
next()
. (Skript 2to3
je dost chytrý na to, aby to převedl správně.)
__next__()
.
next()
, která přebírá jeden nebo víc argumentů, nechá ji skript 2to3
beze změny. Tato třída nemůže být použita jako iterátor, protože její metoda next()
vyžaduje argumenty.
next()
. V takovém případě budeme muset pro získání dalšího prvku posloupnosti volat speciální metodu iterátoru __next__()
. (Alternativně bychom mohli refaktorizovat kód tak, že by lokální proměnná nebyla pojmenována next, ale to za nás 2to3
automaticky neudělá.)
filter()
V Pythonu 2 vracela funkce filter()
seznam, který byl výsledkem filtrování posloupnosti přes funkci, která pro každý prvek posloupnosti vracela hodnotu True
nebo False
. V Pythonu 3 funkce filter()
nevrací seznam, ale iterátor.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | filter(a_function, a_sequence)
| list(filter(a_function, a_sequence))
|
② | list(filter(a_function, a_sequence))
| žádná změna |
③ | filter(None, a_sequence)
| [i for i in a_sequence if i]
|
④ | for i in filter(None, a_sequence):
| žádná změna |
⑤ | [i for i in filter(a_function, a_sequence)]
| žádná změna |
2to3
volání funkce filter()
voláním funkce list()
. Tím se provede průchod přes všechny hodnoty a vrátí se skutečný seznam.
filter()
už obaleno v list()
, nebude 2to3
dělat nic, protože skutečnost, že filter()
vrací iterátor v takovém případě není důležitá.
filter(None, ...)
skript 2to3
nahradí použitím sémanticky shodné generátorové notace seznamu.
for
, kdy stejně dochází k průchodu celou posloupností, není nutné provádět žádné změny.
filter()
vrací iterátor nebo seznam.
map()
Funkce map()
nyní vrací iterátor. Jde o stejný případ jako u funkce filter()
. (V Pythonu 2 se vracel seznam.)
Poznámky | Python 2 | Python 3 |
---|---|---|
① | map(a_function, 'PapayaWhip')
| list(map(a_function, 'PapayaWhip'))
|
② | map(None, 'PapayaWhip')
| list('PapayaWhip')
|
③ | map(lambda x: x+1, range(42))
| [x+1 for x in range(42)]
|
④ | for i in map(a_function, a_sequence):
| žádná změna |
⑤ | [i for i in map(a_function, a_sequence)]
| žádná změna |
filter()
v nejzákladnějším případě obalí skript 2to3
volání funkce map()
voláním list()
.
map(None, ...)
, vyjadřující funkci identity, převede skript 2to3
na ekvivalentní volání list()
.
map()
lambda funkce, převede 2to3
zápis s využitím odpovídající generátorové notace seznamu.
for
, které stejně procházejí celou posloupností, není nutné provádět žádné změny.
map()
vrací iterátor nebo seznam.
reduce()
V Pythonu 3 byla funkce reduce()
vyňata z globálního prostoru jmen a umístěna do modulu functools
.
Poznámky | Python 2 | Python 3 |
---|---|---|
reduce(a, b, c)
|
|
apply()
V Pythonu 2 existovala globální funkce apply()
, která přebírala funkci f a seznam [a, b, c]
a vrátila f(a, b, c)
. Stejné věci můžeme dosáhnout tím, že funkci zavoláme přímo a před předávaný seznam argumentů připíšeme hvězdičku. V Pythonu 3 již funkce apply()
neexistuje. Musíme použít zápis s hvězdičkou.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | apply(a_function, a_list_of_args)
| a_function(*a_list_of_args)
|
② | apply(a_function, a_list_of_args, a_dictionary_of_named_args)
| a_function(*a_list_of_args, **a_dictionary_of_named_args)
|
③ | apply(a_function, a_list_of_args + z)
| a_function(*a_list_of_args + z)
|
④ | apply(aModule.a_function, a_list_of_args)
| aModule.a_function(*a_list_of_args)
|
[a, b, c]
) přidáním hvězdičky před seznam (*
). Jde o přesný ekvivalent staré funkce apply()
z Pythonu 2.
apply()
ve skutečnosti přebírat tři parametry: funkci, seznam argumentů a slovník s pojmenovanými argumenty. V Pythonu 3 můžeme téhož dosáhnout přidáním hvězdičky před seznam argumentů (*
) a přidáním dvou hvězdiček před slovník pojmenovaných argumentů (**
).
+
má vyšší prioritu než operátor *
, takže kolem a_list_of_args + z
nemusíme přidávat závorky.
2to3
je dost chytrý na to, aby převedl i složitá volání apply()
, včetně volání funkcí z importovaných modulů.
intern()
V Pythonu 2 bylo možné „internovat“ řetězec voláním funkce intern()
, čímž došlo k optimalizaci výkonu při práci s tímto řetězcem. V Pythonu 3 byla funkce intern()
přesunuta do modulu sys
.
Poznámky | Python 2 | Python 3 |
---|---|---|
intern(aString)
| sys.intern(aString)
|
exec
Příkaz exec
se v Pythonu 3 změnil na funkci stejně, jako se na funkci změnil příkaz print
. Funkce exec()
přebírá řetězec, který obsahuje libovolný pythonovský kód, a provede jej, jako kdyby to byl nějaký příkaz nebo výraz. Funkce exec()
se podobá eval()
, ale je ještě mocnější a zlověstnější. Funkce eval()
může vyhodnocovat jediný výraz, ale funkce exec()
může provést více příkazů, importů, deklarací funkcí — v podstatě celý pythonovský program, předaný jako řetězec.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | exec codeString
| exec(codeString)
|
② | exec codeString in a_global_namespace
| exec(codeString, a_global_namespace)
|
③ | exec codeString in a_global_namespace, a_local_namespace
| exec(codeString, a_global_namespace, a_local_namespace)
|
2to3
prostě uzavře kód v podobě řetězce do závorek, protože exec()
je teď funkce a ne příkaz.
exec
mohl přebírat prostor jmen v podobě soukromého prostředí s globálními jmény, ve kterém se měl kód v podobě řetězce provádět. V Pythonu 3 lze dělat totéž. Prostor jmen se funkci exec()
jednoduše předá jako druhý parametr.
exec
umožňoval dokonce přebírat lokální prostor jmen (podobající se prostoru proměnných definovaných uvnitř nějaké funkce). V Pythonu 3 to funkce exec()
dokáže také.
execfile
Původní příkaz execfile
, podobně jako původní příkaz exec
, spouštěl řetězce, ve kterých byl uložen pythonovský kód. Tam, kde exec
přebíral řetězec, execfile
přebíral jméno souboru. Z Pythonu 3 byl příkaz execfile
vyřazen. Pokud opravdu chcete použít soubor s pythonovským kódem a spustit jej (ale nechcete jej přitom jednoduše importovat), můžete stejné funkčnosti dosáhnout otevřením souboru, načtením jeho obsahu, zavoláním globální funkce compile()
(aby byl pythonovský interpret donucen kód přeložit) a nakonec zavoláním nové funkce exec()
.
Poznámky | Python 2 | Python 3 |
---|---|---|
execfile('a_filename')
| exec(compile(open('a_filename').read(), 'a_filename', 'exec'))
|
repr
-literály (zpětné apostrofy)V Pythonu 2 bylo možné získat reprezentaci objektu použitím speciální syntaxe, kdy se libovolný objekt obalil zpětnými apostrofy (backticks; jako například `x`
). V Pythonu 3 tato schopnost stále existuje, ale už ji nemůžeme vyvolat použitím zpětných apostrofů. Místo nich musíme použít globální funkci repr()
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | `x`
| repr(x)
|
② | `'PapayaWhip' + `2``
| repr('PapayaWhip' + repr(2))
|
repr()
funguje na všechno.
2to3
je dost chytrý na to, aby zápis převedl na zanořené volání repr()
.
try...except
Syntaxe pro odchytávání výjimek se mezi verzemi Python 2 a Python 3 mírně změnila.
Poznámky | Python 2 | Python 3 |
---|---|---|
① |
|
|
② |
|
|
③ |
| žádná změna |
④ |
| žádná změna |
as
.
as
funguje i pro odchytávání více typů výjimek najednou.
☞Nouzové odchytávání všech výjimek byste nikdy neměli používat při importování modulů (ani ve většině ostatních případů). Tímto způsobem odchytíte i věci jako
KeyboardInterrupt
(pokud se uživatel pokoušel o přerušení činnosti programu stiskem Ctrl-C) a ztížíte si tím ladění.
raise
Syntaxe pro vyvolávání našich vlastních výjimek se mezi verzemi Python 2 a Python 3 mírně změnila.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | raise MyException
| žádná změna |
② | raise MyException, 'error message'
| raise MyException('error message')
|
③ | raise MyException, 'error message', a_traceback
| raise MyException('error message').with_traceback(a_traceback)
|
④ | raise 'error message'
| nepodporováno |
2to3
vás bude varovat, že nebyl schopen tuto situaci opravit automaticky.
throw
V Pythonu 2 definovaly generátory metodu throw()
. Volání a_generator.throw()
vyvolá výjimku v místě, kde se generátor zastavil. Potom se vrací další hodnota, která je vyprodukována (yield) generátorovou funkcí. V Pythonu 3 je uvedená funkčnost stále k dispozici, ale syntaxe se trochu změnila.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | a_generator.throw(MyException)
| žádná změna |
② | a_generator.throw(MyException, 'error message')
| a_generator.throw(MyException('error message'))
|
③ | a_generator.throw('error message')
| nepodporováno |
2to3
zobrazí varování, které říká, že to budete muset opravit ručně.
xrange()
V Pythonu 2 existovaly dva způsoby získávání hodnot intervalu čísel: funkce range()
vracela seznam a funkce xrange()
, vracela iterátor. V Pythonu 3 funkce range()
vrací iterátor a funkce xrange()
už neexistuje.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | xrange(10)
| range(10)
|
② | a_list = range(10)
| a_list = list(range(10))
|
③ | [i for i in xrange(10)]
| [i for i in range(10)]
|
④ | for i in range(10):
| žádná změna |
⑤ | sum(range(10))
| žádná změna |
2to3
jednoduše změní xrange()
na range()
.
range()
, pak skript 2to3
neví, zda jsme skutečně potřebovali seznam, nebo zda by vyhověl iterátor. V rámci opatrnosti se vracená hodnota převádí na seznam voláním funkce list()
.
xrange()
použita uvnitř generátorového zápisu seznamu, pak je skript 2to3
dost chytrý na to, aby funkci range()
neobalil voláním list()
. Generátorový zápis seznamu bude bez problémů fungovat s iterátorem, který je funkcí range()
vrácen.
for
, takže ani zde není nutné nic měnit.
sum()
pracuje s iterátorem také, takže 2to3
nemusí nic měnit ani zde. Uvedený přístup se, stejně jako v případě metod slovníku, které vracejí pohledy (view) místo seznamů, aplikuje i u funkcí min()
, max()
, sum()
, list()
, tuple()
, set()
, sorted()
, any()
a all()
.
raw_input()
a input()
Python 2 poskytoval pro vyžádání si uživatelského vstupu z příkazové řádky dvě globální funkce. První z nich, zvaná input()
, očekávala, že uživatel vloží pythonovský výraz (vrací se jeho výsledek). Druhá z nich, zvaná raw_input()
, vracela to, co uživatel napsal. Začátečníky to velmi mátlo a považovalo se to za „bradavici“ (wart) na jazyce. Python 3 tuto nepěknost řeší přejmenováním raw_input()
na input()
, takže to funguje způsobem, který většina naivně očekává.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | raw_input()
| input()
|
② | raw_input('prompt')
| input('prompt')
|
③ | input()
| eval(input())
|
raw_input()
mění na input()
.
raw_input()
přebírat vyzývací řetězec jako parametr. Tato možnost je zachována i v Pythonu 3.
input()
a předejte její výsledek funkci eval()
.
func_*
V Pythonu 2 může kód uvnitř funkce přistupovat ke speciálním atributům, které se týkají funkce samotné. V Pythonu 3 byly tyto speciální atributy funkcí přejmenovány, aby se dostaly do souladu s ostatními atributy.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | a_function.func_name
| a_function.__name__
|
② | a_function.func_doc
| a_function.__doc__
|
③ | a_function.func_defaults
| a_function.__defaults__
|
④ | a_function.func_dict
| a_function.__dict__
|
⑤ | a_function.func_closure
| a_function.__closure__
|
⑥ | a_function.func_globals
| a_function.__globals__
|
⑦ | a_function.func_code
| a_function.__code__
|
__name__
(dříve func_name
) obsahuje jméno funkce.
__doc__
(dříve func_doc
) obsahuje dokumentační řetězec, který byl definován ve zdrojovém textu funkce.
__defaults__
(dříve func_defaults
) je n-tice obsahující výchozí hodnoty argumentů pro ty z argumentů, pro které byly výchozí hodnoty definovány.
__dict__
(dříve func_dict
) je prostor jmen uchovávající libovolné atributy funkce.
__closure__
(dříve func_closure
) je n-tice buněk, které obsahují vazby (bindings) na volné proměnné, které se ve funkci používají.
__globals__
(dříve func_globals
) je odkaz na globální prostor jmen modulu, ve kterém byla funkce definována.
__code__
(dříve func_code
) je objekt kódu (code object), reprezentující přeložené tělo funkce.
xreadlines()
V/V objektůV Pythonu 2 měly souborové objekty metodu xreadlines()
, která vracela iterátor procházející souborem po řádcích. Kromě jiného se to hodilo pro cykly for
. Ve skutečnosti to byla tak užitečná metoda, že pozdější verze Pythonu 2 přidaly schopnost iterovat samotným souborovým objektům.
V Pythonu 3 přestala metoda xreadlines()
existovat. Skript 2to3
je schopen převést jednoduché případy, ale v hraničních situacích po vás bude vyžadovat ruční zásah.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | for line in a_file.xreadlines():
| for line in a_file:
|
② | for line in a_file.xreadlines(5):
| žádná změna (vede k nefunkčnímu kódu) |
xreadlines()
bez argumentů, převede toto volání skript 2to3
jen na souborový objekt. V Pythonu 3 zajistí tento zápis stejnou funkčnost: čte se ze souboru řádek po řádku a provádí se tělo cyklu for
.
xreadlines()
s argumentem (počet řádků, které se mají načíst najednou), pak to skript 2to3
neopraví a váš kód selže s vysvětlením AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'
. Opravu pro Python 3 můžete ručně provést změnou xreadlines()
na readlines()
. (Metoda readlines()
teď vrací iterátor, takže je to stejně efektivní, jako bylo xreadlines()
v Pythonu 2.)
☃
lambda
funkce, které akceptují n-tici místo více parametrůV Pythonu 2 jsme mohli definovat anonymní lambda
funkci, která přebírá více parametrů, tím, že jsme ji definovali jako funkci, která přebírá n-tici s určeným počtem položek. V důsledku toho Python 2 „rozbalil“ n-tici do pojmenovaných argumentů, na které jsme se pak mohli uvnitř lambda
funkce odkazovat jménem. V Pythonu 3 můžeme lambda
funkci také předávat n-tici, ale pythonovský interpret ji nerozbalí do pojmenovaných argumentů. Místo toho se budeme muset na jednotlivé argumenty odkazovat pozičním indexem.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | lambda (x,): x + f(x)
| lambda x1: x1[0] + f(x1[0])
|
② | lambda (x, y): x + f(y)
| lambda x_y: x_y[0] + f(x_y[1])
|
③ | lambda (x, (y, z)): x + y + z
| lambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1]
|
④ | lambda x, y, z: x + y + z
| žádná změna |
lambda
funkci, která přebírá n-tici s jedním prvkem, stane se z ní v Pythonu 3 lambda
funkce, která se odkazuje na x1[0]. Jméno x1 je generováno skriptem 2to3
automaticky, na základě pojmenovaných argumentů původní n-tice.
lambda
funkce s dvouprvkovou n-ticí (x, y) bude převedena na x_y s pozičními argumenty x_y[0] a x_y[1].
2to3
zvládne dokonce lambda
funkce s vnořenými n-ticemi pojmenovaných argumentů. Výsledný kód v Pythonu 3 je poněkud nečitelný, ale funguje stejným způsobem, jakým fungoval původní kód v Pythonu 2.
lambda
funkce, které přebírají víc argumentů. Pokud kolem argumentů neuvedeme závorky, chová se Python 2 k zápisu jako k lambda
funkci s více argumenty. Uvnitř lambda
funkce se na pojmenované argumenty odkazujeme jménem jako v každé jiné funkci. V Pythonu 3 tato syntaxe pořád funguje.
V Pythonu 2 se mohly metody tříd odkazovat na objekt třídy, ve které jsou definovány, a také na samotný objekt metody. Reference im_self
odkazovala na objekt instance třídy, im_func
na objekt funkce a im_class
se odkazuje na třídu objektu im_self
. V Pythonu 3 byly tyto speciální atributy metod přejmenovány, aby se dostaly do souladu s pojmenováním ostatních atributů.
Poznámky | Python 2 | Python 3 |
---|---|---|
aClassInstance.aClassMethod.im_func
| aClassInstance.aClassMethod.__func__
| |
aClassInstance.aClassMethod.im_self
| aClassInstance.aClassMethod.__self__
| |
aClassInstance.aClassMethod.im_class
| aClassInstance.aClassMethod.__self__.__class__
|
__nonzero__
V Pythonu 2 jsme mohli vytvářet své vlastní třídy, které se daly používat v booleovském kontextu. Mohli jsme například vytvořit instanci takové třídy a pak ji použít v příkazu if
. Dělalo se to tak, že jsme definovali speciální metodu __nonzero__()
, která vracela True
nebo False
. Ta se volala, kdykoliv byla instance použita v booleovském kontextu. V Pythonu 3 lze dělat totéž, ale jméno metody bylo změněno na __bool__()
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① |
|
|
② |
| žádná změna |
__nonzero__()
volá metoda __bool__()
.
__nonzero__()
, která vyžaduje nějaké argumenty, bude nástroj 2to3
předpokládat, že jsme ji používali pro nějaký jiný účel, a neprovede žádné změny.
Syntaxe pro zápis čísel v osmičkové soustavě (tj. oktalových) se mezi Pythonem 2 a Pythonem 3 mírně změnila.
Poznámky | Python 2 | Python 3 |
---|---|---|
x = 0755
| x = 0o755
|
sys.maxint
V souvislosti se sloučením typů long
a int
pozbyla konstanta sys.maxint
vypovídací přesnost. Tato hodnota může být stále užitečná při zjišťování schopností závislých na platformě. Proto byla v Pythonu ponechána, ale byla přejmenována na sys.maxsize
.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | from sys import maxint
| from sys import maxsize
|
② | a_function(sys.maxint)
| a_function(sys.maxsize)
|
maxint
se stává maxsize
.
sys.maxint
se mění na sys.maxsize
.
callable()
V Pythonu 2 jsme mohli voláním globální funkce callable()
zkontrolovat, zda se dá objekt volat (jako funkce). Z Pythonu 3 byla tato globální funkce vyřazena. Pokud chceme zjistit, zda se dá objekt volat, musíme zkontrolovat, zda má speciální metodu __call__()
.
Poznámky | Python 2 | Python 3 |
---|---|---|
callable(anything)
| hasattr(anything, '__call__')
|
zip()
V Pythonu 2 přebírala globální funkce zip()
libovolný počet posloupností a vracela seznam n-tic. První n-tice obsahovala první položky ze všech posloupností, druhá n-tice obsahovala druhé položky ze všech posloupností a tak dále. V Pythonu 3 vrací funkce zip()
místo seznamu iterátor.
Poznámky | Python 2 | Python 3 |
---|---|---|
① | zip(a, b, c)
| list(zip(a, b, c))
|
② | d.join(zip(a, b, c))
| žádná změna |
zip()
spočívá v obalení návratové hodnoty voláním list()
. Tím dojde k průchodu všemi hodnotami iterátoru vraceného funkcí zip()
a vytvoří se skutečný seznam výsledků.
join()
), funguje iterátor vracený funkcí zip()
bez problémů. Skript 2to3
je dost chytrý na to, aby takové případy detekoval a neprováděl ve vašem kódu žádné změny.
StandardError
V Pythonu 2 byla StandardError
bázovou třídou všech zabudovaných výjimek — až na StopIteration
, GeneratorExit
, KeyboardInterrupt
a SystemExit
. V Pythonu 3 byla třída StandardError
zrušena. Místo ní se používá třída Exception
.
Poznámky | Python 2 | Python 3 |
---|---|---|
x = StandardError()
| x = Exception()
| |
x = StandardError(a, b, c)
| x = Exception(a, b, c)
|
types
Modul types
obsahuje širokou paletu konstant, které nám pomáhají určovat typ objektu. V Pythonu 2 obsahoval konstanty pro všechny primitivní typy, jako jsou dict
a int
. Z Pythonu 3 byly tyto konstanty odstraněny. Místo nich se používá jméno primitivního typu.
Poznámky | Python 2 | Python 3 |
---|---|---|
types.UnicodeType
| str
| |
types.StringType
| bytes
| |
types.DictType
| dict
| |
types.IntType
| int
| |
types.LongType
| int
| |
types.ListType
| list
| |
types.NoneType
| type(None)
| |
types.BooleanType
| bool
| |
types.BufferType
| memoryview
| |
types.ClassType
| type
| |
types.ComplexType
| complex
| |
types.EllipsisType
| type(Ellipsis)
| |
types.FloatType
| float
| |
types.ObjectType
| object
| |
types.NotImplementedType
| type(NotImplemented)
| |
types.SliceType
| slice
| |
types.TupleType
| tuple
| |
types.TypeType
| type
| |
types.XRangeType
| range
|
☞
types.StringType
se převádí nabytes
a ne nastr
, protože „řetězec“ v Pythonu 2 (ne Unicode řetězec, ale obyčejný řetězec) je ve skutečnosti jen posloupností bajtů odpovídajících určitému znakovému kódování.
isinstance()
Funkce isinstance()
kontroluje, zda je objekt instancí určité třídy nebo typu. V Pythonu 2 jsme mohli předat n-tici typů a isinstance()
vrátila True
, pokud byl objekt jedním z uvedených typů. V Pythonu 3 lze dělat totéž, ale předávání stejného typu dvakrát se považuje za nežádoucí (deprecated).
Poznámky | Python 2 | Python 3 |
---|---|---|
isinstance(x, (int, float, int))
| isinstance(x, (int, float))
|
basestring
Python 2 pracoval s dvěma typy řetězců: Unicode a ne-Unicode. Ale existoval v něm ještě jeden typ, basestring
. Jednalo se o abstraktní typ, nadtřídu jak pro typ str
, tak pro typ unicode
. Nebylo možné ji volat nebo z ní vytvářet instanci přímo, ale mohli jste ji předat globální funkci isinstance()
, když jste chtěli zkontrolovat, zda je objekt buď Unicode, nebo ne-Unicode řetězcem. V Pythonu 3 existuje jediný řetězcový typ, takže důvod k existenci typu basestring
pominul.
Poznámky | Python 2 | Python 3 |
---|---|---|
isinstance(x, basestring)
| isinstance(x, str)
|
itertools
modulePython 2.3 zavedl modul itertools
, který definoval varianty globálních funkcí zip()
, map()
a filter()
, které místo seznamu vracely iterátory. V Pythonu 3 tyto globální funkce vracejí iterátory, takže uvedené funkce byly z modulu itertools
odstraněny. (V modulu itertools
je stále mnoho užitečných funkcí, nejen ty právě zmíněné.)
Poznámky | Python 2 | Python 3 |
---|---|---|
① | itertools.izip(a, b)
| zip(a, b)
|
② | itertools.imap(a, b)
| map(a, b)
|
③ | itertools.ifilter(a, b)
| filter(a, b)
|
④ | from itertools import imap, izip, foo
| from itertools import foo
|
itertools.izip()
použijte jednoduše globální funkci zip()
.
itertools.imap()
použijte jednoduše map()
.
itertools.ifilter()
se stává filter()
.
itertools
v Pythonu 3 pořád existuje. Jen v něm chybí funkce, které byly přesunuty do globálního prostoru jmen. Skript 2to3
je dost chytrý na to, aby odstranil importy, které neexistují, a ponechal ostatní importy nedotčené.
sys.exc_type
, sys.exc_value
, sys.exc_traceback
U Pythonu 2 se v modulu sys
nacházely tři proměnné, které jsme mohli používat během obsluhy výjimky: sys.exc_type
, sys.exc_value
, sys.exc_traceback
. (Ve skutečnosti mají původ už v Pythonu 1.) Už od Pythonu 1.5 bylo používání těchto proměnných považováno za nežádoucí (deprecated) ve prospěch sys.exc_info()
, což je funkce vracející n-tici se všemi třemi hodnotami. V Pythonu 3 byly tyto tři individuální proměnné nakonec odstraněny. Musíme používat funkci sys.exc_info()
.
Poznámky | Python 2 | Python 3 |
---|---|---|
sys.exc_type
| sys.exc_info()[0]
| |
sys.exc_value
| sys.exc_info()[1]
| |
sys.exc_traceback
| sys.exc_info()[2]
|
Pokud jsme v Pythonu 2 chtěli použít generátorovou notaci seznamu, která předepisovala iteraci přes n-tici, nemuseli jsme hodnoty n-tice uzavírat do kulatých závorek. V Pythonu 3 se explicitní závorky vyžadují.
Poznámky | Python 2 | Python 3 |
---|---|---|
[i for i in 1, 2]
| [i for i in (1, 2)]
|
os.getcwdu()
V Pythonu 2 byla k dispozici funkce pojmenovaná os.getcwd()
, která vracela aktuální pracovní adresář jako (ne-Unicode) řetězec. Protože moderní souborové systémy umí pracovat se jmény adresářů v libovolném znakovém kódování, zavedl Python 2.3 funkci os.getcwdu()
. Funkce os.getcwdu()
vracela aktuální pracovní adresář jako Unicode řetězec. V Pythonu 3 existuje jediný řetězcový typ (Unicode), takže os.getcwd()
je vším, co potřebujeme.
Poznámky | Python 2 | Python 3 |
---|---|---|
os.getcwdu()
| os.getcwd()
|
V Pythonu 2 jsme mohli metatřídy vytvářet buď definicí argumentu metaclass
v deklaraci třídy, nebo definicí speciálního atributu __metaclass__
na úrovni třídy. V Pythonu 3 byl tento atribut třídy odstraněn.
Poznámky | Python 2 | Python 3 |
---|---|---|
① |
| žádná změna |
② |
|
|
③ |
|
|
2to3
je dost chytrý na to, aby zkonstruoval platnou deklaraci třídy dokonce i v případech, kdy třída dědí z jedné nebo více bázových tříd.
Zbytek zde popsaných „oprav“ ve skutečnosti nejsou opravy jako takové. Tyto úpravy nemění podstatu, ale styl. Jde o věci, které fungují jak v Pythonu 2, tak v Pythonu 3. Vývojáři Pythonu ale mají zájem na tom, aby byl pythonovský kód tak jednotný, jak je to jen možné. Z tohoto pohledu existuje oficiální Python style guide (Průvodce stylem jazyka Python), který popisuje — až do nesnesitelnosti — všechny možné detaily, které vás téměř určitě nezajímají. A když už 2to3
vytváří tak mohutnou infrastrukturu pro konverzi pythonovského kódu z jedné podoby do druhé, vzali si autoři za své přidat pár nepovinných rysů, které by zlepšily čitelnost vašich pythonovských programů.
set()
; explicitně)V Pythonu 2 bylo jediným možným vyjádřením definice množinového literálu volání set(posloupnost)
. V Pythonu 3 tato možnost stále funguje, ale čistší způsob spočívá v použití nového zápisu množinového literálu: složené závorky. Funguje to pro všechny množiny s výjimkou prázdné množiny. Je to tím, že slovníky používají složené závorky také a zápis {}
byl již vyhrazen pro prázdný slovník a ne pro prázdnou množinu.
☞Skript
2to3
standardně množinové literály zapsané pomocíset()
neupravuje. Pokud chceme tuto úpravu povolit, uvedeme při volání2to3
na příkazovém řádku -f set_literal (f jako fix).
Poznámky | Před | Po |
---|---|---|
set([1, 2, 3])
| {1, 2, 3}
| |
set((1, 2, 3))
| {1, 2, 3}
| |
set([i for i in a_sequence])
| {i for i in a_sequence}
|
buffer()
(explicitně)Pythonovské objekty implementované v jazyce C exportují takzvané „rozhraní bloku paměti“ (buffer interface), které umožňuje ostatnímu pythonovskému kódu přímo číst blok paměti a zapisovat do něj. (Je to přesně tak mocné a děsivé, jak to zní.) V Pythonu 3 byla funkce buffer()
přejmenována na memoryview()
. (Ve skutečnosti je to sice o něco komplikovanější, ale rozdíly můžete téměř určitě ignorovat.)
☞Skript
2to3
standardně funkcibuffer()
neopravuje. Pokud chceme tuto úpravu povolit, uvedeme při volání2to3
na příkazovém řádku -f buffer.
Poznámky | Před | Po |
---|---|---|
x = buffer(y)
| x = memoryview(y)
|
Navzdory drakonickým pravidlům pro používání bílých znaků (whitespace) při odsazování a předsazování se Python chová docela volně k používání bílých znaků v jiných oblastech. Uvnitř seznamů, n-tic, množin a slovníků se mohou bílé znaky objevit před a za čárkami bez škodlivých účinků. Jenže Průvodce stylem jazyka Python říká, že před čárkami se nemá psát žádná mezera a za čárkou se má psát jedna. Ačkoliv se zde jedná o čistě estetickou záležitost (kód funguje tak jako tak, v Pythonu 2 i v Pythonu 3), skript 2to3
tuto věc může volitelně opravit.
☞Skript
2to3
standardně psaní bílých znaků kolem čárek neupravuje. Pokud chceme tuto úpravu povolit, uvedeme při volání2to3
na příkazovém řádku -f wscomma.
Poznámky | Před | Po |
---|---|---|
a ,b
| a, b
| |
{a :b}
| {a: b}
|
V pythonovské komunitě postupně vznikla celá řada používaných obratů. Některé se datují až k Pythonu 1, jako například cyklus while 1:
. (Až do verze 2.3 neměl Python opravdový booleovský typ, takže vývojáři místo pravdivostních hodnot používali 1
a 0
.) Moderní pythonovští programátoři by své mozky měli natrénovat na modernější podobu takových obratů.
☞Skript
2to3
standardně opravu běžných obratů neprovádí. Pokud chceme tuto úpravu povolit, uvedeme při volání2to3
na příkazovém řádku -f idioms.
Poznámky | Před | Po |
---|---|---|
|
| |
type(x) == T
| isinstance(x, T)
| |
type(x) is T
| isinstance(x, T)
| |
|
|
© 2001–11 Mark Pilgrim