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 で読み込もうとするとエラーが発声するので要注意である.