Python 2/3 両対応のコードを書くための future_builtins の使い方

Python 2 と Python 3 で動作が変わった組み込み関数に, filter や map がある. Python 2 でも Python 3 と同じ動作をさせるために, future_builtins というライブラリが提供されているが, Python 2/3 両対応するには少し注意が必要である. 他のいくつかの方法も含めて, Python 3 の仕様で動作する filter や map 関数の Python 2/3 両対応の書き方について紹介する.

Python 2 での filter 関数や map 関数はリストを返していたが, Python 3 ではイテレータを返すようになった. Python 2 のコードを Python 3 のコードに変換する 2to3 では, Python 2 の

map(lambda x: x * 2, [1, 2, 3])

のコードを

list(map(lambda x: x * 2, [1, 2, 3]))

に書き換えることで対応している. 下のコードは Python 2 でも正常にするため, Python 2/3 両対応のコードとして使える. しかし, map がイテレータを返すという仕様をうまく利用することは出来ない.

Python 2 では標準ライブラリの itertools に ifilter や imap といった関数が定義されていて, これらはイテレータを返し, それぞれ Python 3 の filter, map に対応する. しかしながら Python 3 の itertools にはこれらの関数が定義されていないため, Python 2/3 両対応のコードには使いづらい.

Python 2 の標準ライブラリとして提供されている future_builtins を使うと, Python 3 のようにイテレータを返す filter や map を使うことが出来る. 使い方は通常のライブラリを読み込むときと同じで, 以下にようにする.

from future_builtins import filter, map

Python 3 では future_builtins は提供されていないので, このままでは Python 2/3 両対応のコードにはならない. 以下のように try 文を用いて, Python 3 で future_builtins を読み込めなかった場合のエラー処理を行なうと, Python 2/3 両対応のコードにすることが出来る.

try:
    from future_builtins import filter, map
except ImportError:
    pass

print 関数を Python 2 でも用いる, __future__.print_function は Python 3 で import してもエラーにならないが, future_builtins を Python 3 で読み込もうとするとエラーが発声するので要注意である.