Python2.6以降では次のコードを入れておくことでPython 3系の挙動に一部の関数や命令の挙動を変更できる。
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
Python 2.6以降の2系 (2.6, 2.7) に限定して、以下も使用できる。
from future_builtins import ascii, filter, hex, map, oct, zip
future_builtins
は、__future__
と異なりPython 3系ではこのモジュールは存在しないので、
両系対応時にはバージョンを確認の上でインポートするか、try/exceptで囲うような対応が必要になる。
各モジュールの詳細については、次のドキュメントを参照すると良い。
- http://docs.python.jp/2/library/__future__.html
- http://docs.python.jp/2/reference/simple_stmts.html#future
- http://docs.python.jp/2/library/future_builtins.html
Python 2.7でも事情は同じで、上記と同じコードを使用できる。
本文章でPython 2.6を含めているのは、主にRHEL/CentOS 6でPython 2.6が今後数年生き残る可能性がある(と、筆者は理解している)ためである。
結論として、Python 2.6でもPython 2.7でも__future__
とfuture_builtins
の挙動で特に留意するべき重大な違いはない。
pyenv
を始めとした方法でPythonランタイムの選択が許されている人は、原則としてPython 2.6は使うべきではない。自由にランタイムを選べるのなら、Python 2.7つまりPython 2系全体を使用しない方向で考える方が良いだろう。ただし、使用したいライブラリ(やPythonランタイム)が2系にしか対応していないという理由でPython 2系に縛られているというケースは、現在でも考えられる。
__future__
はPython2.1で導入された比較的古いモジュールで、Pythonの旧バージョンで新バージョンの挙動を一部先に取り込みたいときに使われてきた。現在ではPython 2系と3系の挙動を近づけるために言及されることが多いが、必ずしも3系対応のために存在するのではない。
__future__
の一部機能については、Python 2.6でも使用する意味がなく、害はないものの混乱を招く可能性はある。future 文 にある説明は以下の通りである。
Python 2.6 が認識する機能は、 unicode_literals, print_function, absolute_import, division, generators, nested_scopes, with_statement です。 generators, with_statement, nested_scopes は Python 2.6 以上では常に有効なので冗長です。
future_builtins
は「Python 2.x に存在するけれども、 Python 3 では異なった動作をするために、 Python 2.x のビルトイン名前空間に追加できない関数を提供」するために提供されるモジュールで、6種類の関数が定義されている。Python 2.6で導入された。
前述の通りPython 3系には存在しないモジュールであるため、3系で使用しようとすると無視されるのではなくエラーとなる。2系と3系の両方を意識したコーディングでは、若干の注意を要するように思われる。
future_builtins
でインポートされるそれぞれの関数は、Python 3系の同等の組み込み関数と同等の挙動に近くなるよう工夫されているが、挙動が異なるものもある。全く同一の挙動を示すと仮定しては行けない。
# ごく正確にはデータ型からして違うが、この手のオブジェクトに対してデータ型を見て挙動を変更するのはPythonでは余りおすすめできないので、そもそも考察しない。
典型的にはmap()
の第一引数がNone
であった際の挙動が異なる。
Python 2.7.12 (default, Jul 20 2016, 12:19:03)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from future_builtins import map
>>> list(map(None, [1, 2, 3]))
[(1,), (2,), (3,)]
Python 2.7の future_builtins.map
の実体は itertools.imap()
であるとされる。
この関数はドキュメントにある通り、第一引数function
がNone
のときの挙動が独特である。
function が None の場合、 imap() は引数のタプルを返します。
Python 3系のmap()
関数にはこの挙動はない(参考)。
実際、第一引数function
に対してNoneを与えると、Python3系ではエラーとなる。
Python 3.5.2 (default, Jul 29 2016, 11:13:25)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> list(map(None, [1, 2, 3]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable