Nacházíte se zde: Domů Ponořme se do Pythonu 3

Úroveň obtížnosti: ♦♦♦♦♦

Přepis kódu do Pythonu 3 s využitím 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)

 

Ponořme se

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.

Příkaz 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)
  1. Prázdný řádek vytiskneme voláním print() bez zadání argumentů.
  2. Jednu hodnotu vytiskneme voláním print() s jedním argumentem.
  3. Dvě hodnoty oddělené mezerou vytiskneme voláním print() s dvěma argumenty.
  4. V tomhle je malá finta. Pokud jsme v Pythonu 2 ukončili příkaz 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.
  5. V Pythonu 2 jsme mohli výstup přesměrovat do roury (pipe) — například na 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.

Literály Unicode-řetězců

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'
  1. Řetězcové literály s prefixem Unicode jsou jednoduše převedeny na obyčejné řetězcové literály, které v Pythonu 3 vždy vyjadřují Unicode řetězce.
  2. Surové Unicode řetězce (raw; ve kterých Python neprovádí interpretaci zpětného lomítka jako zahájení escape posloupnosti) jsou převedeny na surové řetězce. V Pythonu 3 jsou surové řetězce vždy v Unicode.

Globální funkce 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)

Datový typ 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)
  1. Z desítkových číselných literálů pro „dlouhý“ integer (long) se staly desítkové literály pro typ integer.
  2. Z šestnáctkových číselných literálů pro „dlouhý“ integer (long) se staly šestnáctkové literály pro typ integer.
  3. V Pythonu 3 přestala existovat původní funkce long(), protože přestal existovat typ long (dlouhý integer). K převodu proměnné na celé číslo použijeme funkci int().
  4. Pokud chceme zkontrolovat, zda je proměnná typu integer, zjistíme její typ a porovnáváme ho s int (nikoliv s long).
  5. Ke kontrole datového typu můžeme použít i funkci isinstance(). Při zjišťování, zda jde o celočíselný typ, se opět odkážeme na int a ne na long.

Porovnání <>

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:
  1. Jednoduché porovnání.
  2. Složitější porovnání mezi třemi hodnotami.

Slovníková metoda 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)
  1. Nejjednodušší forma.
  2. Operátor 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.
  3. Ale na druhou stranu zde ze stejného důvodu musíme uzavřít 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íč.)
  4. Operátor + 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á.
  5. U tohoto zápisu musí být kolem y in a_dictionary závorky určitě uvedeny, protože operátor + má vyšší prioritu než operátor in.

Slovníkové metody, které vracejí seznamy

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
  1. Skript 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.
  2. Další konverze pohledu na seznam — tentokrát u metody items(). Stejnou věc provede 2to3 s metodou values().
  3. Python 3 už nepodporuje metodu iterkeys(). Použijte keys(), a pokud je to nezbytné, udělejte z pohledu iterátor voláním funkce iter().
  4. 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.
  5. 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().

Moduly, které byly přejmenovány nebo reorganizovány

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 BaseHTTPServer
import SimpleHTTPServer
import CGIHttpServer
import http.server
  1. Modul http.client implementuje nízkoúrovňovou knihovnu, která vytváří požadavky na HTTP zdroje a interpretuje související HTTP odpovědi.
  2. Modul http.cookies poskytuje pythonovské rozhraní pro cookies prohlížeče, které se posílají v HTTP hlavičce HTTP hlavička.
  3. Modul http.cookiejar manipuluje se soubory na disku, které oblíbené webové prohlížeče používají k ukládání cookies.
  4. Modul 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
from urllib import FancyURLopener
from urllib import urlencode
from urllib.request import FancyURLopener
from urllib.parse import urlencode
from urllib2 import Request
from urllib2 import HTTPError
from urllib.request import Request
from urllib.error import HTTPError
  1. Starý modul 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í.
  2. Původní modul 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.
  3. Modul urllib.parse z Pythonu 3 obsahuje všechny funkce z původního modulu urlparse z Pythonu 2.
  4. Modul urllib.robotparser zpracovává soubory robots.txt.
  5. Třída 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.
  6. Třída 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
import urllib
print urllib.urlopen('http://diveintopython3.org/').read()
import urllib.request, urllib.parse, urllib.error
print(urllib.request.urlopen('http://diveintopython3.org/').read())

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 anydbm
import whichdb
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 DocXMLRPCServer
import SimpleXMLRPCServer
import xmlrpc.server

Ostatní moduly

Poznámky Python 2 Python 3
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO
import io
try:
    import cPickle as pickle
except ImportError:
    import pickle
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
  1. Mezi běžné obraty v Pythonu 2 patřil pokus o 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.
  2. Podobný obrat se používal pro importování nejrychlejší implementace pickle. V Pythonu 3 už to nedělejte. Modul pickle to udělá za vás.
  3. Modul 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í.
  4. Modul copyreg přidává podporu „piklení“ pro uživatelské typy definované v C.
  5. Modul queue implementuje frontu pro více producentů a více konzumentů.
  6. Modul socketserver poskytuje obecné (generické) bázové třídy pro implementaci různých druhů soketových serverů.
  7. Modul configparser zpracovává konfigurační soubory ve stylu INI.
  8. Modul 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í.
  9. Modul subprocess umožňuje vytvářet procesy, připojovat se k jejich rourám (pipe) a získávat jejich návratové kódy.

Relativní importy uvnitř balíčku

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
  1. Pokud potřebujeme importovat celý modul odněkud z našeho balíčku, použijeme novou syntaxi 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.
  2. Pokud chceme importovat určitou třídu nebo funkci z jiného modulu přímo do prostoru jmen našeho modulu, přidáme k cílovému modulu jako prefix relativní cestu bez koncového lomítka. V tomto případě se 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.

Metoda iterátoru 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())
class A:
    def next(self):
        pass
class A:
    def __next__(self):
        pass
class A:
    def next(self, x, y):
        pass
žádná změna
next = 42
for an_iterator in a_sequence_of_iterators:
    an_iterator.next()
next = 42
for an_iterator in a_sequence_of_iterators:
    an_iterator.__next__()
  1. V nejjednodušším případě nyní místo volání metody iterátoru next() předáváme iterátor globální funkci next().
  2. Pokud máme funkci, která vrací iterátor, zavoláme ji a výsledek předáme funkci next(). (Skript 2to3 je dost chytrý na to, aby to převedl správně.)
  3. Pokud definujeme svou vlastní třídu a míníme ji použít jako iterátor, definujeme speciální metodu __next__().
  4. Pokud definujeme svou vlastní třídu a ta shodou okolností obsahuje metodu pojmenovanou 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.
  5. Tohle je trošku ošemetné. Pokud máme lokální proměnnou pojmenovanou next, pak bude mít přednost před novou globální funkcí 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á.)

Globální funkce 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
  1. V nejzákladnějším případě obalí skript 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.
  2. Pokud je ale volání funkce 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á.
  3. Speciální syntaxi filter(None, ...) skript 2to3 nahradí použitím sémanticky shodné generátorové notace seznamu.
  4. V kontextu podobajícímu se cyklům for, kdy stejně dochází k průchodu celou posloupností, není nutné provádět žádné změny.
  5. Ani zde se nemusí dělat žádné změny, protože generátorová notace seznamu bude iterovat přes všechny prvky posloupnosti, a to může udělat, ať už filter() vrací iterátor nebo seznam.

Globální funkce 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
  1. Stejně jako u filter() v nejzákladnějším případě obalí skript 2to3 volání funkce map() voláním list().
  2. Speciální syntaxi map(None, ...), vyjadřující funkci identity, převede skript 2to3 na ekvivalentní volání list().
  3. Pokud je prvním argumentem map() lambda funkce, převede 2to3 zápis s využitím odpovídající generátorové notace seznamu.
  4. V kontextu jako u cyklů for, které stejně procházejí celou posloupností, není nutné provádět žádné změny.
  5. Ani zde se nemusí dělat žádné změny, protože generátorová notace seznamu předepisuje průchod přes všechny prvky posloupnosti, a to může udělat, ať už map() vrací iterátor nebo seznam.

Globální funkce 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)
from functools import reduce
reduce(a, b, c)

Globální funkce 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)
  1. V nejjednodušším případě můžeme funkci při volání předat seznam argumentů (skutečný seznam, jako například [a, b, c]) přidáním hvězdičky před seznam (*). Jde o přesný ekvivalent staré funkce apply() z Pythonu 2.
  2. V Pythonu 2 může funkce 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ů (**).
  3. Zde se operátor + používá pro zřetězení seznamů. Operátor + má vyšší prioritu než operátor *, takže kolem a_list_of_args + z nemusíme přidávat závorky.
  4. Skript 2to3 je dost chytrý na to, aby převedl i složitá volání apply(), včetně volání funkcí z importovaných modulů.

Globální funkce 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)

Příkaz 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)
  1. V nejjednodušším případě skript 2to3 prostě uzavře kód v podobě řetězce do závorek, protože exec() je teď funkce a ne příkaz.
  2. Původní 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.
  3. Původní příkaz 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é.

Příkaz 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))
  1. Připomeňme si, že x může být cokoliv — třída, funkce, modul, primitivní datový typ atd. Funkce repr() funguje na všechno.
  2. V Pythonu 2 mohly být zpětné apostrofy zanořeny, což vedlo k tomuto druhu matoucích (ale platných) výrazů. Skript 2to3 je dost chytrý na to, aby zápis převedl na zanořené volání repr().

Příkaz 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
try:
    import mymodule
except ImportError, e
    pass
try:
    import mymodule
except ImportError as e:
    pass
try:
    import mymodule
except (RuntimeError, ImportError), e
    pass
try:
    import mymodule
except (RuntimeError, ImportError) as e:
    pass
try:
    import mymodule
except ImportError:
    pass
žádná změna
try:
    import mymodule
except:
    pass
žádná změna
  1. Místo čárky se za typem výjimky v Pythonu 3 používá nové klíčové slovo as.
  2. Klíčové slovo as funguje i pro odchytávání více typů výjimek najednou.
  3. Pokud výjimku jen odchytíme, ale ve skutečnosti nás nezajímá možnost přistupování k samotnému objektu výjimky, pak se syntaxe používaná v Pythonu 2 shoduje se syntaxí v Pythonu 3.
  4. Podobně, pokud používáme záchranu v podobě odchytávání všech výjimek, je syntaxe identická.

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í.

Příkaz 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
  1. Při použití nejjednodušší formy, vyvolání výjimky bez uživatelské chybové zprávy, se syntaxe nezměnila.
  2. Změny si povšimneme, když chceme vyvolat výjimku s uživatelským chybovým hlášením. Python 2 odděloval třídu výjimky a uživatelskou zprávu čárkou. Python 3 předává chybovou zprávu jako parametr.
  3. Python 2 podporoval při složitější syntaxi vyvolání výjimky s uživatelským zpětným trasováním (stack trace). V Pythonu 3 toho můžeme dosáhnout také, ale syntaxe se docela liší.
  4. V Pythonu 2 jsme mohli vyvolat výjimku, aniž jsme zadávali třídu výjimky. Stačilo zadat chybovou zprávu. V Pythonu 3 to již není možné. Skript 2to3 vás bude varovat, že nebyl schopen tuto situaci opravit automaticky.

Metoda generátorů 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
  1. V nejjednodušším případě generátor vyvolává výjimku bez uživatelské chybové zprávy. V tomto případě se syntaxe v Pythonu 3 vůči Pythonu 2 nezměnila.
  2. Pokud generátor vyvolává výjimku s uživatelskou chybovou zprávou, musíme řetězec se zprávou předat vytvářenému objektu výjimky.
  3. Python 2 podporoval vyvolání výjimky, která byla tvořena pouze uživatelským chybovým hlášením. Python 3 toto chování nepodporuje a skript 2to3 zobrazí varování, které říká, že to budete muset opravit ručně.

Globální funkce 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
  1. V nejjednodušším případě skript 2to3 jednoduše změní xrange() na range().
  2. Pokud kód pro Python 2 používal 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().
  3. Pokud by byla funkce 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.
  4. Bez problémů bude s iterátorem fungovat i cyklus for, takže ani zde není nutné nic měnit.
  5. Funkce 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().

Globální funkce 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())
  1. V nejjednodušším případě se raw_input() mění na input().
  2. V Pythonu 2 mohla funkce raw_input() přebírat vyzývací řetězec jako parametr. Tato možnost je zachována i v Pythonu 3.
  3. Pokud chcete, aby se opravdu vyhodnocoval pythonovský výraz zadaný uživatelem, použijte funkci input() a předejte její výsledek funkci eval().

Atributy funkcí 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__
  1. Atribut __name__ (dříve func_name) obsahuje jméno funkce.
  2. Atribut __doc__ (dříve func_doc) obsahuje dokumentační řetězec, který byl definován ve zdrojovém textu funkce.
  3. Atribut __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.
  4. Atribut __dict__ (dříve func_dict) je prostor jmen uchovávající libovolné atributy funkce.
  5. Atribut __closure__ (dříve func_closure) je n-tice buněk, které obsahují vazby (bindings) na volné proměnné, které se ve funkci používají.
  6. Atribut __globals__ (dříve func_globals) je odkaz na globální prostor jmen modulu, ve kterém byla funkce definována.
  7. Atribut __code__ (dříve func_code) je objekt kódu (code object), reprezentující přeložené tělo funkce.

Metoda 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)
  1. Pokud jste byli zvyklí volat 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.
  2. Pokud jste byli zvyklí volat 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
  1. Pokud jsme definovali 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.
  2. 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].
  3. Skript 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.
  4. Můžeme definovat 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.

Atributy speciálních metod

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__

Speciální metoda __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
class A:
    def __nonzero__(self):
        pass
class A:
    def __bool__(self):
        pass
class A:
    def __nonzero__(self, x, y):
        pass
žádná změna
  1. Při vyhodnocování instance v booleovském kontextu se v Pythonu 3 místo __nonzero__() volá metoda __bool__().
  2. Pokud ale máme definovánu metodu __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.

Oktalové literály

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)
  1. Z maxint se stává maxsize.
  2. Jakékoliv použití sys.maxint se mění na sys.maxsize.

Globální funkce 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__')

Globální funkce 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
  1. Nejjednodušší způsob dosažení původního chování funkce 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ů.
  2. V kontextu, kde se již využívá iterace přes všechny položky posloupnosti (jako například při volání této metody 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.

Výjimka 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)

Konstanty modulu 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í na bytes a ne na str, 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í.

Globální funkce 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))

Datový typ 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 module

Python 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
  1. Místo itertools.izip() použijte jednoduše globální funkci zip().
  2. Místo itertools.imap() použijte jednoduše map().
  3. Z itertools.ifilter() se stává filter().
  4. Modul 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]

Generátory seznamů nad n-ticemi

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)]

Funkce 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()

Metatřídy

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
class C(metaclass=PapayaMeta):
    pass
žádná změna
class Whip:
    __metaclass__ = PapayaMeta
class Whip(metaclass=PapayaMeta):
    pass
class C(Whipper, Beater):
    __metaclass__ = PapayaMeta
class C(Whipper, Beater, metaclass=PapayaMeta):
    pass
  1. Deklarace metatřídy v místě deklarace třídy fungovala v Pythonu 2 a funguje stejně i v Pythonu 3.
  2. Deklarace metatřídy pomocí atributu třídy fungovala v Pythonu 2, ale v Pythonu 3 již ne.
  3. Skript 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.

Věci týkající se stylu

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ů.

Množinové literály (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}

Globální funkce 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ě funkci buffer() 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)

Bílé znaky kolem čárek (explicitně)

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}

Běžné obraty (explicitně)

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
while 1:
    do_stuff()
while True:
    do_stuff()
type(x) == T isinstance(x, T)
type(x) is T isinstance(x, T)
a_list = list(a_sequence)
a_list.sort()
do_stuff(a_list)
a_list = sorted(a_sequence)
do_stuff(a_list)

© 2001–11 Mark Pilgrim