Další změny
Změny v syntaxi
Parametry funkce umístěné za args musí být vždy keywords-only (klíč=hodnota). V seznamu lze použít i samotnou hvězdičku. Za hvězdičkou pak stejně jako u argv musíme uvádět už jen keywords-only argumenty. Hvězdička označuje předem neznámý počet argumentů.
Můžeme ji také použít při zápisu podobném tomuto:
>>> a,*b,c=1,2,3,4,5
>>> a
1
>>> b
[2, 3, 4]
>>> c
5
Byla přidána také jedna z flexibilnějších cest, jak vytvořit slovník, resp. jak ho vytvořit z jiných typů.
>>> values = [("a",1),("b",2)]
>>> {k:v for k,v in values}
{'a': 1, 'b': 2}
Zápis binárních a ostatních číselných soustav se teď nově provádí přes:
>>> i=0b101010
>>> print(i)
42
>>> i=0o52
>>> print(i)
42
Cesta zpět vede přes nové funkce bin() a oct():
>>> bin(42)
'0b101010'
>>> oct(42)
'0o52'
Klíčová slova, která zastupují v pythonu nějakou funkci, nemohou být přepsána. K těmto slovům se v novém pythonu přidala další. Tento zápis již není v 3.0 možný:
>>> True=2
>>> print True
2
V Pythonu 3.0 hodí chybu:
>>> True = 2
File "<stdin>", line 1
SyntaxError: assignment to keyword
K těmto novým slovům patří as, with, True, False a None.
Python 3.0 mění také práci s metatřídami. Už nebude možné dále používat proměnnou metaclass, ale musíme použít parametr třídy metaclass.
>>> class M(type):
... pass
...
>>> class C(metaclass=M):
... pass
...
Cyklus for už není tak benevolentní ke svému vstupu a zápis z Pythonu 2.x:
>>> for x in 1,2,3,4:
... print x
...
1
2
3
4
Už nebude možný a budeme muset použít:
>>> for x in (1,2,3,4):
... print(x)
...
1
2
3
4
V definici funkce nebudeme moci používat typ tuple, ale musíme ho nahradit jedinou proměnnou. Toto by v řadě 2.x ještě prošlo:
>>> def foo(a,(b,c)):
... print a,b,c
...
>>> foo(1,(2,3))
1 2 3
Ale nyní musíme skript upravit:
>>> def foo(a,b):
... print(a,b)
...
>>> foo(1,(2,3))
1 (2, 3)
Funkce raw_input() byla přejmenována na input().
>>> var = input("piš:")
piš:Foo
>>> print(var)
Foo
Operátor <> je nahrazen operátorem !=. Klíčové slovo exec již nadále není klíčové slovo a místo něj byla zavedena funkce exec(). Jako funkce teď již nebere jako argument objekt se souborem, ale pouze text. Již z minulého dílu je jasné, že zápisy u"" nebo 10L končí, protože Python teď již nedělá rozdíl mezi dlouhými a krátkými celými čísly a text je vždy unicode. Klasické třídy byly kompletně z Pythonu odstraněny a byly nahrazeny novým stylem známým již z minulých řad, kde ale tento styl nebyl jako výchozí.
Velké změny se týkají také výjimek. API bylo vyčištěno a nové vlastnosti přidány. Všechny výjimky nově musí být odvozeny přímo či nepřímo od BaseException. Výjimka StandardError byla odstraněna a také se dále nechovají jako sekvence. Jako náhrada se používají argumenty. To znamená, že „raise Exception, args“ už fungovat nebude a musíme použít „raise Exception(args)“.
Nástroj 2to3
Ukázkový zdrojový kód
Ukázkový kód jsem složil z několika problémových částí, které nás budou v příštích měsících potkávat, a na nich si můžeme zkusit, jak se s nimi 2to3 vypořádá. Schválně jsem tedy použil takové konstrukce, které v Pythonu 3.0 nepojedou. Na druhou stranu nejedná se o všechny, takový skript by pak byl nepřiměřeně dlouhý.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
l = long(1000000)
print "%d %s"%(l/2,u"ěščřžý")
print
if 1 < "":
print type(1/2)
print 1/2
f = open("testfile","wb")
f.write("ěščř\n")
f.close()
f = os.tmpfile()
f.write("foo")
f.close()
Správný výstup programu:
cx@ubuntu:~$ python2.5 test.py; cat testfile
500000 ěščřžý
<type 'int'>
0
ěščř
Co o kódu řekne Python 2.6
Moc nám toho Python 2.6 o ukázkovém kódu neřekl. Prakticky informuje pouze o špatně zvolené podmínce.
500000 ěščřžý
test.py:10: DeprecationWarning: comparing unequal types not supported in 3.x
if 1 < "":
<type 'int'>
0
ěščř
Použití nástroje 2to3
Nástroj 2to3 je koncipován tak, aby nám dodal patch, se kterým můžeme dál pracovat, upravovat ho a hlavně aplikovat.
cx@ubuntu:~$ 2to3 test.py
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
--- test.py (original)
+++ test.py (refactored)
@@ -3,13 +3,13 @@
import os
-l = long(1000000)
-print "%d %s"%(l/2,u"ěščřžý")
-print
+l = int(1000000)
+print("%d %s"%(l/2,"ěščřžý"))
+print()
if 1 < "":
- print type(1/2)
- print 1/2
+ print(type(1/2))
+ print(1/2)
f = open("testfile","wb")
f.write("ěščř\n")
RefactoringTool: Files that need to be modified:
RefactoringTool: test.py
Lze ho aplikovat i na celé adresáře a on bude rekurzivně hledat zdrojové kódy a generovat pro ně patch. Patch samotný se kopíruje na standardní výstup a další informace na standardní chybový výstup. Proto není problém získat samotný patch.
Je-li patch v pořádku, přejdeme k jeho aplikaci:
cx@ubuntu:~$ cat test.patch | patch -p0
patching file test.py
Co je potřeba doladit
--- testB.py 2008-12-14 22:17:39.000000000 +0100
+++ testA.py 2008-12-14 22:12:19.000000000 +0100
@@ -7,16 +7,17 @@
print("%d %s"%(l/2,"ěščřžý"))
print()
-if 1 < "":
+if 1 < 2:
print(type(1/2))
print(1/2)
f = open("testfile","wb")
-f.write("ěščř\n")
+f.write("ěščř\n".encode("utf8"))
f.close()
-f = os.tmpfile()
-f.write("foo")
+import tempfile
+f = tempfile.TemporaryFile()
+f.write("foo".encode("iso-8859-2"))
f.close()
Výstup z nástroje 2to3 sice vyladí jednoduché věci kolem typů a funkce print, ale s těmi složitějšími si neporadí. Stačilo mu předhodit funkci, která s Pythonem 3.0 zmizí, a bylo zapotřebí ručního zásahu, i když má funkce svoji náhradu v jiném modulu.
Další možnosti 2to3
Může se stát, že 2to3 opraví něco špatně. Jedná se o modulární nástroj a my můžeme použít na nás zdrojový kód pouze pár z těchto modulů. Také si můžeme napsat vlastní. Moduly se nacházejí v adresáři /usr/lib/python3.0/lib2to3/fixes/.
List dostupných modulů dostaneme buď vypsáním obsahu zmíněného adresáře nebo v použitelnější formě pomocí:
cx@ubuntu:~$ 2to3 -l
Available transformations for the -f/--fix option:
apply
basestring
buffer
callable
[...]
Jednotlivé moduly pak můžeme aplikovat pomocí parametru -f.
Závěr
Problémy s Pythonem 3.0 budou a takovýchto ručních zásahů bude potřeba víc. Jak jsem psal již minule, ne všechny projektu používají zasažené části pythonu, takže se klidně může stát, že 2to3 a pár ručních oprav budou dostačující. Množství malých skriptů nebude dělat problémy vůbec. Webové stránky napsané v Pythonu jsou většinou založené na jednom z pythoních frameworků a tam většina práce zůstane na vývojářích daného frameworku. Změny jsou známy již delší dobu, takže se vývojáři podobných projektů většinou vyhýbají postiženým konstrukcím nebo si nechávají cestu, jak z toho ven. Proto by neměl být to neměl být problém ani v tomto směru.
Nezbývá než popřát hodně štěstí.