現在地: ホーム Dive Into Python 3

難易度: ♦♦♦♦♦

2to3を使ってコードをPython 3に移植する

生は楽しく、死は安らかである。厄介なのはその変わり目だ。
— アイザック・アシモフ(の言葉とされる)

 

飛び込む

Python 2で作成したプログラムをPython 3で動くようにするには、実質的にほぼ全てのプログラムに、少なくともちょっとした調整ぐらいは施さなくてはならないだろう。Python 3には2to3という便利なスクリプトがついている。これは実際のPython 2のコードを受け取って、Python 3でも動くように可能な限り自動変換してくれるというものだ。「ケーススタディ: chardetをPython 3に移植する」では、まずどのように2to3を実行するかを説明し、それから自動で直せないものをいくつか示した。この付録では、2to3を使うことで何を自動で修正しうるのかを説明する。

print

Python 2ではprint文であり、何を出力するにせよ、単純にprintの後に続ければよかった。Python 3では、print()は関数だ。だから、出力したいものが何であれ、他の関数と同じようにprint()に引数として渡さなくてはならない。

Notes 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. 空白行を出力するには、print()を引数無しで呼び出せばいい。
  2. 値を一つだけ出力したいなら、print()に一つの引数を渡して呼び出せばいい。
  3. 二つの値をスペースで区切って出力するには、print()を二つの引数を渡して呼び出せばいい。
  4. これは少し手が込んでいる。Python 2では、print文の最後にカンマをつけると、スペースで区切られた値の後にさらにスペースが出力され、改行文字は出力されなかった。Python 3で同じことをするには、キーワード引数としてend=' 'をprint()関数に渡さなくてはならない。つまり、endのデフォルトの値は'\n'(改行文字)になっているので、これをオーバーライドすることで、他の引数が出力された後に改行文字が入らないようにできるのだ。
  5. Python 2では、>>pipe_nameの構文を使うことで — sys.stderrのような — パイプに出力をリダイレクトできた。Python 3ではパイプをfileのキーワード引数として渡す必要がある。つまり、デフォルトではsys.stdout(標準出力)がfileの引数となっているので、これをオーバーライドすることで異なるパイプに出力できるようになるのだ。

Unicode文字列リテラル

Python 2には二つの文字列の型があった: Unicode文字列と非Unicode文字列だ。Python 3には文字列の型は一つしかない: Unicode文字列だ。

Notes Python 2 Python 3
u'PapayaWhip' 'PapayaWhip'
ur'PapayaWhip\foo' r'PapayaWhip\foo'
  1. Unicode文字列はそのまま文字列に変換される。Python 3では文字列は常にUnicodeだからだ。
  2. rawモード(自動的にバックスラッシュでエスケープしないモード)のUnicode文字列はraw文字列に変換される。Python 3では、raw文字列は常にUnicodeだからだ。

unicode()グローバル関数

Python 2にはオブジェクトを文字列に変換するグローバル関数が二つあった: Unicode文字列に変換するunicode()と、非Unicode文字列に変更するstr()だ。Python 3はたった一つの文字列の型、つまりUnicode文字列しか持っていないので、str()関数だけでこと足りるのだ(事実、unicode()は削除されている)。

Notes Python 2 Python 3
unicode(anything) str(anything)

longデータ型

Python 2は非浮動小数点数としてint型とlong型の2つの型を用意していて、intは各プラットフォームごとに設定されたsys.maxintの値以上に大きくなれなかった。一方で、長整数とは数字の最後にLを付けることで定義されるもので、この長整数は、そのつまり、整数より長くなることができた。Python 3にはintと呼ばれる整数型しかなく、これはおおかたPython 2のlong型のように振る舞う。このようにintlongは統合されたので、この二つを区別するための特別な構文もなくなっている。

参考: PEP 237: 長整数と整数の統合

Notes 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. 10進法の長整数リテラルは10進法の整数リテラルになる。
  2. 16進法の長整数リテラルは16進法の整数リテラルになる。
  3. Python 3では、長整数が無くなった関係で、long()関数も廃止されている。変数を整数に直すには、int()関数を使えばいい。
  4. ある変数が整数かどうかを調べるには、その型を取得して(long型ではなく)int型と比較すればいい。
  5. isinstance()関数を使ってデータの型を調べることもできる。ここでも、整数かどうかを調べる時にはlongではなくintを使うこと。

<> 比較

Python 2は、不等性を評価する演算子の!=と同じ意味を表すものとして<>をサポートしていた。Python 3では<>は消えて、!=だけがサポートされている。

Notes Python 2 Python 3
if x <> y: if x != y:
if x <> y <> z: if x != y != z:
  1. 単純な比較。
  2. より複雑な3つの値の比較。

has_key()辞書メソッド

Python 2ではhas_key()というメソッドが辞書にあり、これを用いることで特定のキーが辞書にあるかどうかを調べることができた。Python 3ではこのメソッドは廃止されているので、代わりにin演算子を使う必要がある。

Notes 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. 最も簡単な例。
  2. in演算子はor演算子より優先されるので、x in a_dictionaryy in a_dictionaryを丸括弧でくくる必要はない。
  3. 一方で、この例では必ずx or yを丸括弧でくくる必要がある。これも同じ理由 — inorに優先する — による(注意: このコードは2のコードとはまったく意味が異なる。Pythonはまずx or yを解釈し、もしxブール値の文脈で真ならばxを返し、偽ならばyを返す。それから、その戻り値を取り上げ、それがa_dictionaryのキーなのかどうかをチェックする)
  4. +演算子はin演算子に優先するので、厳密にはx + yに丸括弧をつける必要は無いのだが、とりあえず2to3は括弧をつけてくれる。
  5. この場合は確実にy in a_dictionaryを括弧でくくらなくてはならない。+演算子はin演算子に優先するからだ。

リストを返す辞書メソッド

Python 2では、多くの辞書型のメソッドがリストを返していた。中でも、最もよく使われていたのがkeys(), items(), values()だ。Python 3ではこれら3つのメソッド全てがダイナミックなviewを返す。これは場面によっては、何の問題にもならない。例えば、これらのメソッドが返す値が即座に別の関数に渡され、シーケンス全体がイテレートされるなら別に問題は起きない。しかし、これが大きな問題を引き起こす場合もある。例えば、個々の要素を参照できる完全なリストが必要なところでは、コードは止まってしまうだろう。viewはインデクスによる参照をサポートしてないからだ。

Notes 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()) 変更なし
  1. 2to3は安全な方に転ぶように設計されていて、keys()の戻り値を全てlist()関数で静的なリストに変換するようになっている。こうすればどんな場合でもコードは動くのだが、viewを使うより効率は落ちる。変換したコードに目を通して「リストが本当に必要だろうか? viewを使っても動かないだろうか?」と確かめた方がいい。
  2. 今度はitem()メソッドの戻り値をviewからリストに変換している。2to3values()メソッドにも同じ処理を施す。
  3. Python 3はiterkeys()メソッドをサポートしていない。代わりにkeys()を使い、その上で必要なら、viewをiter()関数を使ってイテレーターに変換すればいい。
  4. 2to3は、リストの内包表記でiterkeys()メソッドが使われている場合を識別し、keys()メソッドに変換してくれる(iter()を呼び出してkeys()を変換することはない)。viewはイテレートできるので、これでも動くのだ。
  5. 2to3は、keys()メソッドがシーケンス全体にわたってイテレートする関数に即座に渡される場合を認識し、keys()の戻り値をlistに変換する必要はないと判断してくれる。例えば、上に挙げられているmin()関数は何の問題もなくviewをイテレートできるのだ。このことはmin()max()sum()list()tuple()set()sorted()any()all()についてあてはまる。

名前が変更されたり再構成されたりしたモジュール

標準ライブラリに入っているモジュールのいくつかは名前が変更されている、他にも、相互に関連のあったモジュールの中には、その関係をより論理的に明解にするために統合されたり再構成されたりしたものがある。

http

Python 3 ではHTTP関連のモジュールのいくつかが統合されて、httpという一つのパッケージにまとめられている。

Notes 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. http.clientモジュールは、HTTPリソースを要求し、HTTPの応答を解釈するための低級ライブラリを実装したものだ。
  2. http.cookiesモジュールはSet-Cookie: HTTPヘッダに送られたクッキーをブラウズするPython的なインターフェイスを提供する。
  3. http.cookiejarモジュールを使えば、一般的なウェブブラウザがcookieを保存するのに使っているディスク上のファイルを取り扱うことができる。
  4. http.serverモジュールは基本的なHTTP サーバーの機能を提供する。

urllib

Python 2では、URLを取得したり、構文解析やエンコードを施したりするためのモジュールはグチャグチャに入り混じっていて、その機能も互いに重なり合っていた。Python 3では、これらのモジュールは全て書き直されて、urllibという1つのパッケージに統合されている。

Notes 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. Python 2で使われていた古いurllibモジュールには様々な関数が入っていて、その中には、データを取得するurlopen()や、URLを構成要素に分割するsplittype()splithost()splituser()などがあった。これらの関数はより論理的に筋が通るように再構成され、新しいurllibパッケージに納められている。2to3は、新しい命名体系に従うように、これらの関数が呼び出されている箇所を修正してくれる。
  2. Python 2に存在したurllib2モジュールは、Python 3ではurllibパッケージに組み込まれている。あなたのお気に入りの関数 — build_opener()メソッドやRequestオブジェクト、HTTPBasicAuthHandlerとその仲間たちなど — は、Python 3でもまだ使えるのだ。
  3. Python3のurllib.parseモジュールの中には、Python 2のurlparseモジュールに含まれていた構文解析関数が全て入っている。
  4. urllib.robotparserモジュールはrobots.txtを解析するものだ。
  5. HTTPリダイレクトなどのスターテスコードを扱うFancyURLopnerクラスは、urllib.requestモジュールから呼び出すことができる。urlencode()関数はurllib.parseに移されている。
  6. Requestオブジェクトはurllib.requestから呼び出せる。一方で、HTTPErrorのような定数はurllib.errorに移されている。

言ってなかったかもしれないが、2to3は関数の呼び出しも修正してくれる。例えば、あるコードがurllibモジュールをインポートして、データ取得のためにurllib.urlopen()を呼び出していた場合、2to3はこのimport文と関数の呼び出しの両方を書き直してくれる。

Notes 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

何種類もあったDBMクローンは全てdbmという一つのパッケージにまとめられている。GNU DBMといった特定の実装が欲しければ、そのモジュールをdbmパッケージからインポートできる。

Notes 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-RPCHTTPを介してRPC(遠隔手続き呼び出し)を行う軽量なメソッドだ。XML-RPCのクライアント用ライブラリやいくつかのXML-RPCサーバーの実装はxmlrpcに統合されている。

Notes Python 2 Python 3
import xmlrpclib import xmlrpc.client
import DocXMLRPCServer
import SimpleXMLRPCServer
import xmlrpc.server

その他のモジュール

Notes 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. Python 2では、まずcStringIO as StringIOというようにインポートしてみて、それでエラーが起これば、StringIOを代わりにインポートするという方法が広く用いられていたが、Python 3でこれをやってはいけない。ioモジュールが代わりにやってくれるからだ。このモジュールは使える中から最も実行速度の速い実装を見つけだして、それを使うように自動で設定してくれる。
  2. 最も速いpickleの実装をインポートするのにも同じようなテクニックが用いられてきてが、これもPython 3ではやってはいけない。pickleモジュールがやってくれることだからだ。
  3. builtinsモジュールの中にはグローバルな関数やクラスや定数が入っていて、これらはPython言語全体で使われている。だから、builtinsモジュールのある関数を変更すると、あらゆる部分に影響が及ぶことになる。builtinsモジュールの関数やクラスを変更することは、とても強力であると同時に非常に恐ろしいことでもあるのだ。
  4. copyregモジュールはCで定義された拡張型をpickle化できるようにするために使われる。
  5. queueモジュールは多生産者-多消費者キューを実装するものだ。
  6. socketserverモジュールは様々な種類のソケットサーバーを実装するための一般的な基底クラスを提供する。
  7. configparserモジュールはINI文法で書かれた設定ファイルを解析する。
  8. reprlibモジュールは組み込みのrepr()関数を再実装したもので、出力するデータの長さを操作できる機能を備えている。
  9. subprocessモジュールはプロセスの起動、パイプへの接続、戻りコードの取得などの機能を提供する。

パッケージ内の相対インポート

パッケージというのは関連したモジュールを集めたもので、あたかも一つのものであるかのように機能する。Python 2では、あるパッケージに含まれる複数のモジュールが相互に参照する必要がある時には、import foofrom foo import Barを使っていた。ここで、Python 2のインタプリタは最初に現在のパッケージにfoo.pyがあるかどうかを調べた後、Pythonのサーチパス (sys.path) にある別のディレクトリに移るという処理をしていた。一方、Python 3では少し異なった処理がなされる。現在のパッケージの中を最初に検索するかわりに、直接Pythonのサーチパスを参照するのだ。もし、あるモジュールに同じパッケージにある別のモジュールをインポートさせたいなら、二つのモジュール間の相対パスを明示しなくてはならない。

例えば、次のようなパッケージがあるとしよう。ここには複数のファイルが同じディレクトリに入っている:

chardet/
|
+--__init__.py
|
+--constants.py
|
+--mbcharsetprober.py
|
+--universaldetector.py

ここで、universaldetector.pyの中でconstants.pymbcharsetprober.pyに含まれる一つのクラスをインポートする必要があるとしたら、どうすればよいだろうか?

Notes Python 2 Python 3
import constants from . import constants
from mbcharsetprober import MultiByteCharSetProber from .mbcharsetprober import MultiByteCharsetProber
  1. パッケージのどこからであれ、同じパッケージのモジュールをインポートしたいなら、from . importという新しい構文を使えばいい。このピリオドは実際には一方のファイル (universaldetector.py) からインポートしたいファイル (constants.py) までの相対パスを表している。この例の場合、二つが同じディレクトリにあるので、相対パスはピリオド一つになる。同じようにして、親ディレクトリ (from .. import anothermodule) からインポートすることもできるし、サブディレクトリからもできる。
  2. 他のモジュールにある特定のクラスや関数を、あなたのモジュールの名前空間に直接インポートしたいなら、対象となるモジュール名の前に相対パス(ただし最後のスラッシュは取ること)を付ければいい。この例の場合、mbcharsetprober.pyuniversaldetector.pyと同じディレクトリにあるので、相対パスはピリオド一つとなる。同じようにして、親ディレクトリ (from ..anothermodule import AnotherClass) からインポートすることもできるし、サブディレクトリからもできる。

next()イテレータ メソッド

Python 2 では、イテレータはシーケンスの中の次の要素を返すnext()というメソッドを持っていた。このメソッドはPython 3にもあるが、これとは別に一つのイテレータを引数にとるnext()というグローバル関数も用意されている。

Notes Python 2 Python 3
anIterator.next() next(anIterator)
a_function_that_returns_an_iterator().next() next(a_function_that_returns_an_iterator())
class A:
    def next(self):
        pass
class A:
    def __next__(self):
        pass
class A:
    def next(self, x, y):
        pass
変更なし
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. これは最も簡単な例で、イテレータのnext()メソッドを呼び出す代わりに、グローバル関数のnext()にそのイテレータを渡している。
  2. イテレータを返す関数があれば、この関数を呼び出して、その戻り値をnext()関数に渡すようにすればいい(2to3スクリプトは賢いので、これを正しく変換してくれる)。
  3. もし、独自のクラスを定義してイテレータとして使うつもりなら、__next__()という特別なメソッドを定義すればいい。
  4. クラスの中にたまたまnext()という名前のメソッドが含まれていて、しかもそのメソッドが引数を一つ以上とるものであった場合、2to3はそのメソッドには手を加えない。next()メソッドが引数を取るものである以上、このクラスをイテレータとして使うことはできない。
  5. この例は少し複雑だ。nextという名前のローカル変数があった場合、この変数はグローバル関数のnext()より優先される。この例だと、シーケンスの次の要素を取得するにはイテレータの__next__()という特別なメソッドを呼び出さなければならない(あるいは、ローカル変数の名前をnext以外に変えてコードを書きなおすこともできるが、2to3が自動でそのような処理をすることはない)。

filter()グローバル関数

filter()関数とは、個々の要素につきTrueFalseを返す関数を使ってシーケンスをフィルタリングするものだが、Python 2ではその戻り値としてリストを返していた。しかし、Python 3ではfilter()関数はリストではなくイテレーターを返すようになっている。

Notes Python 2 Python 3
filter(a_function, a_sequence) list(filter(a_function, a_sequence))
list(filter(a_function, a_sequence)) 変更なし
filter(None, a_sequence) [i for i in a_sequence if i]
for i in filter(None, a_sequence): 変更なし
[i for i in filter(a_function, a_sequence)] 変更なし
  1. この最も基本的な例では、2to3list()関数でfilter()を括っている。このlist()というのは、渡された引数全体を単純にイテレートして、そのリストを返す関数だ。
  2. 一方で、もしfilter()が既にlist()で括られているならば、2to3は何もしない。filter()がイテレータを返そうが、この場合には何の影響も無いからだ。
  3. filter(None, ...)という特殊な構文があるが、2to3はこれを同じ意味を表すリスト内包表記に置き換えてくれる。
  4. map()がシーケンス全体をイテレートするforループに使われているような場合には、何の変更も必要ない。
  5. この場合も何も変更する必要はない。このリスト内包表記はシーケンス全体をイテレートするものなので、filter()がイテレーターを返そうがリストを返そうが同じように処理できるからだ。

map()グローバル関数

filter()とほぼ同様に、map()もイテレータを返すようになっている(Python 2ではリストを返している)。

Notes 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): 変更なし
[i for i in map(a_function, a_sequence)] 変更なし
  1. filter()の場合と同様に、この最も基本的な例では、2to3map()list()で括っている。
  2. map(None, ...)という特殊な構文(これは恒等関数である)があるが、2to3list()を用いて同じ意味を表すように書き換えてくれる。
  3. もしmap()の最初の引数がlambda関数なら、2to3はこれを等値なリスト内包表記に置き換える。
  4. map()がシーケンス全体をイテレートするforループに使われているような場合には、何の変更も必要ない。
  5. この場合も何も変更する必要はない。このリスト内包表記はシーケンス全体をイテレートするものなので、map()がイテレーターを返そうがリストを返そうが同じように処理できるからだ。

reduce()グローバル関数

Python 3では、reduce()関数はグローバル名前空間から取り除かれ、functoolsモジュールの中に置かれている。

Notes Python 2 Python 3
reduce(a, b, c)
from functools import reduce
reduce(a, b, c)

apply()グローバル関数

Python 2にはapply()というグローバル関数があった。これは関数fとリスト[a,b,c]を引数にとり、f(a,b,c)を返すものだった。これは関数を直接呼び出して、アスタリスクを前に付けた引数のリストを渡すことで同じことを実現できる。Python 3ではapply()関数は廃止されているので、このアスタリスクを使った記法に変えなくてはならない。

Notes 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. 最も簡単な例。前にアスタリスク (*) を付けた引数のリスト([a,b,c]のような実際のリスト)を使って関数を呼び出すことができる。これはPython 2のapply()関数とまったく同じ意味を表すものである。
  2. Python 2では、apply()関数は実のところ3つの引数をとることができた: 関数、引数のリスト、そしてキーワード引数の辞書だ。Python 3 では、引数のリストの前にアスタリスク (*) をつけ、キーワード引数の辞書の前に2つのアスタリスク (**) をつけることで同じことを実現できる。
  3. ここでリストの連結に使われている+演算子は*演算子に優先するので、a_list_of_args + zのまわりを丸括弧で括る必要はない。
  4. 2to3スクリプトは賢いので、複雑なapply()の呼び出しも処理できる。例えば、ここではインポートされたモジュールに含まれている関数が呼び出されている。

intern()グローバル関数

Python 2 では、intern()関数を呼び出して文字列を隔離し、パフォーマンスの最大化を図ることができた。Python 3ではintern()関数はsysモジュールに移されている。

Notes Python 2 Python 3
intern(aString) sys.intern(aString)

exec

printはPython 3で関数になったが、これと同じ変更がexec文にも加えられた。exec()関数は任意のPythonのコードを含む文字列をとり、その文字列を文や式として実行する。exec()eval()に似ているが、eval()よりもっと強力であり、そして邪悪でもある。eval()関数は一つの式しか評価できないのに対して、exec()は複数の文やimport文、関数定義など — これらは本質的に一つのPythonプログラムを文字列に落としたものだ — を実行できるのだ。

Notes 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. これは最も簡単な例で、2to3スクリプトは単純に文字列に直されたコードを丸括弧で括っている。exec()は文ではなく関数だからだ。
  2. 従来のexec文は名前空間、つまり引数の文字列が実行される際の個別の環境を引数にとることができた。Python 3も同じことができる。exec()関数の二番目の引数として名前空間を渡せばよいだけだ。
  3. さらに複雑なことに、従来のexec文はローカル名前空間(関数の中で定義された変数名など)を引数にとることができた。Python 3のexec()関数でも同じことができる。

execfile

従来のexecと同じように、Python 2のexecfile文は文字列をPythonのコードであるかのように実行するものだった。この二つの違いは、execは文字列をとるがexecfileはファイル名をとるということにあった。Python 3では、execfile文は廃止されている。Pythonコードが書かれたファイルを実行する必要があり、単純にインポートしたくない理由がある場合には、そのファイルを開いて読みだし、compile()関数でそのファイルの内容をコンパイルさせた上で、exec()関数を呼び出すことで実質的に同じことを実現できる。

Notes Python 2 Python 3
execfile('a_filename') exec(compile(open('a_filename').read(), 'a_filename', 'exec'))

reprリテラル(バック)

Python 2では、どんなオブジェクトでもバッククォートで括れば(例えば`x`)、そのオブジェクトの評価結果を取得できた。Python 3では、このバッククォートの構文は廃止されているが、グローバル関数のrepr()で同じことができる。

Notes Python 2 Python 3
`x` repr(x)
`'PapayaWhip' + `2`` repr('PapayaWhip' + repr(2))
  1. 覚えておいてほしいのだが、xはクラスでも関数でモジュールでも標準のデータ型でも何でもよいのだ。repr()関数はどのような引数を渡しても動いてくれる。
  2. Python 2 では、バッククォートをネストできたので、この種の(正しいことは正しいのだが)分かりにくい式を作ることもできた。2to3は賢いので、このような式をちゃんとrepr()をネストした形に変換してくれる。

try...except

この例外処理の構文は、Python 2とPython 3では微妙に異なっている。

Notes 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
変更なし
try:
    import mymodule
except:
    pass
変更なし
  1. 例外型の後にカンマを付ける代わりに、Python 3ではasというキーワードを使う。
  2. asは様々な型の例外を一度に処理できる。
  3. 例外が出ても、例外オブジェクトを参照する気がなければ、構文はPython 2とPython 3とでまったく変わらない。
  4. 同じように、全ての例外を一つのフォールバックで処理するなら、構文を変更する必要はない。

モジュールをインポートする場合(もっと言えば、大抵の場合)に、一つのフォールバックで全ての例外を処理しようとしてはいけない。そうすると、KeyboardInterrupt(これはユーザーがプログラムを中断するためにCtrl-Cを押したときに送出される)といった例外も捕えてしまうし、エラーをデバッグするのも難しくなってしまう。

raise

あなた独自の例外を送出するための構文は、Python 2とPython 3とで微妙に異なっている。

Notes Python 2 Python 3
raise MyException 変更されていない
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' サポートされていない
  1. この最も単純な例では、エラーメッセージを出さずに例外を送出している。この構文はまったく変わっていない。
  2. 違いはエラーメッセージと 共に例外を送出する際に明らかになる。Python 2は例外クラスとメッセージをカンマで区切っていたが、Python 3ではエラーメッセージを引数として渡すのだ。
  3. Python 2は自前のトレースバック(スタックトレース)と一緒に例外を送出するという、もっと複雑な構文をサポートしていた。Python 3でも同じことができるが、構文はかなり異なっている。
  4. Python 2では、例外クラスを書かずともエラーメッセージだけで例外を送出できた。Python 3ではこれはもう廃止されている。2to3は、この構文については自動で修正できなかったと警告を出してくれるだろう。

ジェネレータのthrowメソッド

Python 2では、ジェネレータにはthrow()メソッドがあった。これは例えば、a_generator.throw()というように呼び出すことで、ジェネレータが停止した位置で例外を送出し、さらにジェネレータがyieldする次の値を返させることができた。Python 3では、この関数はまだ使えるが、構文が多少異なっている。

Notes Python 2 Python 3
a_generator.throw(MyException) 変更なし
a_generator.throw(MyException, 'error message') a_generator.throw(MyException('error message'))
a_generator.throw('error message') サポートされていない
  1. 最も簡単な型で、ジェネレータは例外をエラーメッセージ無しで送出している。この場合、構文はPython 2とPython 3とで変わっていない。
  2. ジェネレータがエラーメッセージと一緒に例外を送出する場合は、エラーメッセージの文字列を例外の引数として送出時に渡さなければならない。
  3. raiseの場合と同様に、Python 2では例外クラスを出さずに、エラーメッセージだけで例外を送出できたが、Python 3はもはやこの構文をサポートしていない。2to3スクリプトは、この部分のコードを手で直す必要があると警告を出してくれるだろう。

xrange() グローバル関数

Python 2では、一定の範囲で数列を生成するには二つの方法があった: リストを返すrange()とイテレータを返すxrange()だ。Python 3では、range()はイテレータを返すように変更され、xrange()は削除されている。

Notes 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): 変更なし
sum(range(10)) 変更なし
  1. 最も簡単な例。2to3スクリプトはxrange()range()に変更する。
  2. Python 2で書かれたコードがrange()を使っている場合、2to3スクリプトは、そこでリストがどうしても必要なのか、それともイテレータでもよいのか判断できないので、どちらの場合でも良いように、戻り値をlist()関数を使ってリストに直してくれる。
  3. xrange()関数がリスト内包表記で使われていた場合には、戻り値をリストに直す意味は無い。リスト内包表記はイテレータでも動くからだ。
  4. 同様に、forループはイテレータでも普通に動くので、何の変更も加えなくてよい。
  5. sum()関数もイテレータを処理できるので、ここでも2to3はまったく変更を加えない。リストの代わりにviewを返すように変更された辞書のメソッドの場合と同じように、min()max()sum()list()tuple()set()sorted()any()all()は何の影響を受けないのだ。

raw_input() / input()グローバル関数

Python 2には、コマンドライン上でユーザーに入力を求めるための二つのグローバル関数があった。一つ目はinput()で、これにはPythonの式が入力されることになっていた(その上で評価した結果を返してくれる)。二つ目はraw_input()で、これはユーザーがタイプしたものをそのまま返してくれるものだった。この区別は初心者にとって何ともややこしいもので、Pythonの「こぶ」だと考えられていた。Python 3では、raw_input()の名前はinput()に変更され、この「こぶ」は切り落とされている。つまり、人々の直感に合った動きをするように変更されたのである。

Notes Python 2 Python 3
raw_input() input()
raw_input('prompt') input('prompt')
input() eval(input())
  1. 最も簡単な例。raw_input()input()になっている。
  2. Python 2では、raw_input()関数はプロンプトを引数としてとることができた。これはPython 3でも残されている。
  3. ユーザーに入力してもらったPythonの式を評価するという処理を行いたいなら、input()関数を使ってその戻り値をeval()に渡せばいい。

func_* 関数属性

Python 2では、関数の内部からその関数の特殊な属性を参照ができた。Python 3では、これらの特殊な関数属性の名前が、他のオブジェクトの属性名との一貫性を保つために変更されている。

Notes 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. __name__属性(以前はfunc_name)にはその関数の名前が入っている。
  2. __doc__属性(以前はfunc_doc)は関数のソースコードで定義したドキュメント文字列が入っている。
  3. __defaults__属性(以前はfunc_defaults)はタプルで、中にはその関数に設定されているデフォルト値が入っている。
  4. __dict__属性(以前はfunc_dict)はその関数の名前空間で、任意の関数属性をサポートしている。
  5. __closure__属性(以前は、func_closure)はその関数の引数以外の変数に対するバインディングの入ったセル群からなるタプルである。
  6. __globals__属性(以前はfunc_globals)はその関数が定義されたモジュールのグローバル名前空間を参照するためのものだ。
  7. __code__属性(以前はfunc_code)はコンパイルされた関数本体を表すコードオブジェクトである。

xreadlines() I/O メソッド

Python 2では、ファイルオブジェクトはxreadlines()というメソッドを持っていたが、これは一度に一行だけファイルを読んでいくイテレータを返すものだった。これはとりわけforループで使うのに便利であり、実際に、あまりにも便利だったので、Python 2の後の方のバージョンではファイルオブジェクトそのものを代わりに使っても動くように変更が加えられたぐらいだ。

Python 3では、xreadlines()メソッドは廃止されている。2to3は簡単なものなら直せるが、より複雑なコードには自ら手を入れる必要があるだろう。

Notes Python 2 Python 3
for line in a_file.xreadlines(): for line in a_file:
for line in a_file.xreadlines(5): 変更なし(動作しない)
  1. xreadlines()を引数無しで呼び出している場合、2to3はこれをファイルオブジェクトに変換する。Python 3では、両者はまったく同じ処理 — ファイルを一度に一行だけ読み、forループの本体を実行する — を行うのだ。
  2. xreadlines()を引数(一度に読む行数を表す)をつけて呼び出している場合、2to3はこれを修正してはくれない。もし、Python3でそのコードを実行したならば、AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'と送出されて止まってしまうだろう。ここで、コードのxreadlines()readlines()に手で直せばPython 3でも動くようになるはずである(readlines()メソッドは、現在ではイテレータを返すようになっているので、実行速度もPython 2のxreadlines()と変わらない)。

複数の引数をとる代わりにタプルをとるlambda関数

Python 2では匿名のlambda関数を作成でき、さらにその関数が複数の要素を持つタプルを引数にとるように定義することで、複数の引数を扱うことができた。この時、Python 2は実質的にタプルをアンパックして名前の付いた変数の形に直し、lambda関数内部で(名前によって)変数を参照できるようにしていた。Python 3でもlambda関数にタプルを渡すことはできる。しかし、Python 3のインタープリタはタプルを名前の付いた変数にアンパックしてくれないので、個々の変数にはインデクスを使って参照しなければならない。

Notes 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 変更されていない
  1. lambda関数が一つの要素からなるタプルを引数にとるように定義されている場合、この関数はPython 3では、x1[0]という形で参照をおこなうlambda関数になる。このx1という変数名は、元のタプルに含まれていた変数名に基づいて2to3が自動で生成してくれる。
  2. 2つの要素からなるタプル(x, y)を引数にとるlambda関数は、x_yというタプルを引数にとり、x_y[0]x_y[1]という形で参照するように変換される。
  3. 2to3スクリプトはネストしたタプルを引数に取るような、より複雑なlambda関数も扱える。その結果生成されるPython 3のコードは少し読みにくいが、Python 2の古いコードと同じように動いてはくれる。
  4. 複数の引数をとるlambda関数を定義することもできる。引数が括弧で括られていなければ、Python 2は単純にこれを複数の引数を取るlambda関数として扱ってくれ、他の関数と同様に、引数名によって値を参照することもできた。この構文はPython 3でも同じように使える。

特殊メソッド属性

Python 2では、あるクラスのメソッドはそのメソッドオブジェクトのみならず、そのメソッドが属するクラスオブジェクトを参照することもできた。例えば、im_selfはインスタンスオブジェクト、im_funcは関数オブジェクト、im_classim_selfのクラスをそれぞれ表していた。Python 3では、他の属性の命名規則に合わせて、これらの特別なメソッド属性の名前が変更されている。

Notes 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__特殊メソッド

Python 2では、ブール演算として使える独自のクラスを作ることができ、例えばその独自のクラスのインスタンスをif文で使うことができた。この場合、TrueFalseかのどちらかを返す__nonzero__()という特別なメソッドを定義する必要があり、実際にブール演算の際に呼び出されるのはこのメソッドであった。Python 3でも同じことができるが、この特別なメソッドの名前は__bool__()に変更されている。

Notes Python 2 Python 3
class A:
    def __nonzero__(self):
        pass
class A:
    def __bool__(self):
        pass
class A:
    def __nonzero__(self, x, y):
        pass
変更なし
  1. インスタンスがブール演算として使われる時には、Python 3では__nonzero__()の代わりに__bool__()が呼び出される。
  2. ただし、__nonzero__()を引数をとるメソッドとして定義している場合、2to3はこれが何か別の目的で使われているのだと判断するので、何の修正も加えられない。

8進数リテラル

Python 2とPython 3とでは、8進数を表すための構文が多少異なっている。

Notes Python 2 Python 3
x = 0755 x = 0o755

sys.maxint

long型とint型が統合されたため、sys.maxint定数はもはや正確なものではない。しかし、この値は各プラットフォームにおける何らかの最大値を決めるのに役立つかもしれないので、sys.maxsizeという名前で残されている。

Notes Python 2 Python 3
from sys import maxint from sys import maxsize
a_function(sys.maxint) a_function(sys.maxsize)
  1. maxintはmaxsizeに変更される。
  2. sys.maxintはどのように使われていても、すべてsys.maxsizeに置き換えられる。

callable()グローバル関数

Python 2では、callable()というグローバル関数を使うことで、あるオブジェクトが(関数のように)呼び出せるかどうかをチェックできた。Python 3では、このグローバル関数は削除されている。オブジェクトが呼び出し可能かどうかを調べるには、__call__()という特別なメソッドが存在しているかどうかをチェックすればいい。

Notes Python 2 Python 3
callable(anything) hasattr(anything, '__call__')

zip()グローバル関数

Python 2には、zip()という任意の数のシーケンスを引数にとるグローバル関数があり、これは次のようなタプルのリストを返すものだった。つまり、このリストの一番目のタプルは、引数として渡された各々のシーケンスの一番目の要素で構成され、二番目のタプルは、各々のシーケンスの二番目の要素で構成され……というようにして構築されるリストだ。Python 3では、zip()はリストの代わりにイテレータを返すようになっている。

Notes Python 2 Python 3
zip(a, b, c) list(zip(a, b, c))
d.join(zip(a, b, c)) 変更なし
  1. 最も簡単な例。zip()の戻り値をlist()で括ることで(このlist()zip()の戻り値をイテレートして、その結果のリストを返してくれる)、従来のzip()とおなじ振る舞いをさせることができる。
  2. シーケンスの全ての要素に渡ってすぐにイテレートされるような場合(例えばこの例のようにjoin()メソッドが使われている場合)には、別にイテレータでも上手く動いてくれる。2to3は賢いので、このようなケースを認識して、変更を加えないでおいてくれる。

StandardError例外

Python 2では、StandardErrorStopIterationGeneratorExitKeyboardInterruptSystemExitの4つを除く全ての組み込み例外の基底クラスであった。Python 3では、StandardErrorは削除され、その代わりにExceptionが用意されている。

Notes Python 2 Python 3
x = StandardError() x = Exception()
x = StandardError(a, b, c) x = Exception(a, b, c)

typesモジュールの定数

typesモジュールには、オブジェクトの型を調べるのに役立つ様々な定数が入っている。Python 2ではdictintなど、全ての標準型に対応する定数が含まれていたが、Python 3ではこれらの定数は削除されている。この代わりとしては、単純にその標準型の名前を使えばいい。

Notes 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.StiringTypestrではなくbytesに対応している。Python 2の「文字列」(Unicode文字列ではなくただの文字列)とは、実のところ、ある特定の文字コードによって表現されたバイト列のシーケンスだからだ。

isinstance()グローバル関数

isinstance()関数はオブジェクトが特定のクラスのインスタンス(あるいは特定の型のオブジェクト)であるかどうかをチェックするものだ。Python 2では、型オブジェクトを要素にもつタプルを渡した場合、オブジェクトの型がそのタプルに含まれていればTrueを返していた。Python 3でも基本的には同じだが、同じ型を二度渡すことは非推奨とされている。

Notes Python 2 Python 3
isinstance(x, (int, float, int)) isinstance(x, (int, float))

basestringデータ型

Python 2は二つの文字列の型があった: Unicode文字列と非Unicode文字列だ。しかし、実際にはこの二つ以外にbasestringという型があった。これは抽象型ではなく、文字列型とUnicode文字列型のスーパークラスだった。この型は呼び出すことも直接インスタンス化することもできなかったが、これをグローバル関数のisinstance()に渡すことで。オブジェクトがUnicode文字列と非Unicode文字列のいずれかであるかを判別できた。文字列型が一つしかないPython 3にbasestringを残す意味はないので、すでに削除されている。

Notes Python 2 Python 3
isinstance(x, basestring) isinstance(x, str)

itertoolsモジュール

Python 2.3からitertoolsモジュールが加わったが、これはグローバル関数のzip()map()filter()の各々について、リストではなくイテレータを返すように改変したものを定義していた。Python 3では、これらのグローバル関数はイテレータを返すようになっているので、この3つの関数はitertoolsから削除されている(ただし、itertoolsモジュールに含まれているのはこの3つの関数だけではないことに注意。itertoolsには他にも便利な関数がまだまだたくさん入っている)。

Notes 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. itertools.izip()の代わりとしては、単純にグローバル関数のzip()を使えばいい。
  2. itertools.imap()の代わりにはmap()を使う。
  3. itertools.ifilter()filter()になる。
  4. itertoolsモジュールはPython 3にもまだ残っている。今回の変更では、単にグローバル名前空間に移った関数が消えただけだ。2to3スクリプトは賢いので、もはや存在していない関数をインポートしている部分だけを修正し、その他の部分には手をつけないでいてくれる。

sys.exc_type, sys.exc_value, sys.exc_traceback

Python 2のsysモジュールには、例外が処理されている最中に参照できる変数が3つ入っていた: sys.exc_typesys.exc_valuesys.exc_tracebackの3つだ(実のところ、この3つのデータはPython 1のころからあるものだ)。Python 1.5でこの3つの値が入ったタプルを返すsys.exc_info関数ができたため、それ以後これらの変数は非推奨となっていたが、Python 3でついに削除されることになった。これからはsys.exc_infoを使わなくてはならない。

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

タプルを利用したリスト内包表記

Python 2では、リスト内包表記がタプルをイテレートするときは、そのタプルの値を丸括弧で括る必要はなかった。しかし、Python 3では明示的に括弧で括る必要がある。

Notes Python 2 Python 3
[i for i in 1, 2] [i for i in (1, 2)]

os.getcwdu() 関数

Python 2には現在の作業ディレクトリを(非Unicode)文字列で返すos.getcwd()という関数があった。現代的なファイルシステムはどんな文字エンコードのディレクトリ名も扱えるので、Python2.3ではos.get.cwdu()が導入された。このos.getcwdu()とは現在の作業ディレクトリ名をUnicode文字列で返すものだ。Python 3では、文字列型は(Unicode文字列の)1つしかないので、os.getcwd()だけでこと足りるようになっている。

Notes Python 2 Python 3
os.getcwdu() os.getcwd()

メタクラス

Python 2では、クラスを定義する際にmetaclassに値を渡すか、クラスレベルを表す特別な属性である__metaclass__を定義することでメタクラスを作ることができた。Python 3では、このクラスレベル属性は削除されている。

Notes Python 2 Python 3
class C(metaclass=PapayaMeta):
    pass
変更されていない
class Whip:
    __metaclass__ = PapayaMeta
class Whip(metaclass=PapayaMeta):
    pass
class C(Whipper, Beater):
    __metaclass__ = PapayaMeta
class C(Whipper, Beater, metaclass=PapayaMeta):
    pass
  1. Python 2ではクラスを定義する際にメタクラスを定義できたが、これはPython 3でもできる。
  2. Python 2ではクラス属性でメタクラスを定義できたが、Python 3ではできない。
  3. 2to3スクリプトは賢いので、仮にそのクラスが1つ以上の基底クラスから継承したものであっても、正しくクラスを定義する部分を書き換えてくれる。

スタイルの問題

以下にリストされている残りの「修正」は、実のところ本質的な修正が加えられたものではない。つまり、スタイルは変更されたがその実質は何も変えられていないので、結局のところ、これらはPython 3でも従来通り動くのだ。しかし、Pythonの開発者はコードをできるかぎり統一的なものにすることに大きな関心を寄せていて、この目的のために、公式のPythonスタイルガイドというものがあって、読者の皆様が特に気にする必要がないような、本当に細かい部分までいちいち — しかも気が滅入るほど詳しく — 説明がなされているぐらいなのだ。まあ、Pythonのコードを次から次へと変換してくる2to3というすばらしいツールがあるのだから、コードの作成者は可読性を高めるために、ついでに修正を施していくべきだろう。

set()リテラル (explicit)

Python 2では、集合を定義するにはset(a_sequence)というように呼び出すほか無かった。この方法はPython 3でも使えるが、より明解に表したいなら、新しく導入された記法を用いればいい: 波括弧だ。これは基本的にどんな集合を作るのにも使えるが、空集合だけは生成できない。辞書も波括弧を記法に使うため、{}は空集合ではなく空の辞書を生成してしまうのだ。

2to3set()をデフォルトでは修正しない。これを修正させるには、コマンドラインで2to3を起動するときに、明示的に-f set_literalというオプションをつけなくてはならない。

Notes Before After
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()グローバル関数 (explicit)

Cで実装されたPythonオブジェクトは「バッファインターフェイス」を公開できる。これによって、他のPythonコードがメモリブロックを直接読み書きできるようになる(そう、これは強力だが、その半面とても恐ろしいことでもあるのだ)。Python 3では、buffer()memoryview()に名前が変更された(実際はもっと複雑な変更が加えられているのだが、特にその違いを意識する必要はないだろう)。

2to3buffer()をデフォルトでは修正しない。これを修正させるには、コマンドラインで2to3を起動するときに、明示的に-f bufferというオプションをつけなくてはならない。

Notes Before After
x = buffer(y) x = memoryview(y)

カンマの周りの空白文字 (explicit)

Pythonは字下げと字上げのための空白文字についてはひどく厳しいのに、他の部分での空白文字の扱いについてはかなりリベラルである。例えば、リストやタプル、集合、辞書の中においては、カンマの後にも前にも空白文字をつけることができ、それで何の問題も起きなかった。しかし、Pythonスタイルガイドは、カンマの直前にはスペースを置かず、直後にはスペースを一つだけ付けるべきだと明言している。これは純粋に審美的な問題なのだが(空白文字をどう置くにせよ、Python2でもPython3でもコードは動くのだ)、2to3はオプションでこれを修正する機能を備えている。

2to3はカンマの周りの空白文字をデフォルトでは修正しない。これを修正させるには、コマンドラインで2to3を起動するときに、明示的に-f wscommaというオプションをつけなくてはならない。

Notes Before After
a ,b a, b
{a :b} {a: b}

慣用的表現 (explicit)

Pythonコミュニティの中で築き上げられてきた慣用的な表現は多数あるが、その中のいくつか(例えば、while 1: ループ)は、Python 1の頃にまで起源を遡ることができる(Pythonはバージョン2.3まで本物のブール型を持っていなかったので、開発者は代わりに10を使っていたのだ)。現代的なPythonプログラマは、新しい方の表現を使うように頭を慣らしていくべきだろう。

2to3はカンマの周りの空白文字をデフォルトでは修正しない。これを修正させるには、コマンドラインで2to3を起動するときに、明示的に-f wscommaというオプションをつけなくてはならない。

Notes Before After
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– Mark Pilgrim
© Fukada, Fujimoto(日本語版)