filter, map に指定する関数
この記事は Python Tips Advent Calendar 2012 10日目の記事です。
通常、filter, map の第一引数には関数(callable なオブジェクト)を指定しますが、これは None であっても構いません。
None を指定した場合、lambda x: x と大体同じ意味になります*1。
>>> filter(None, [0,1,[],3,None]) [1, 3] >>> map(None, [1,2]) [1, 2]
暗黙bool値変換 で書いたように、x が 0 や [] や None だった場合は False として扱われるので、そういった要素を除けるときに使えます。
map は、この例だと全く意味が無いように見えるかもしれませんが、例えば以下のように複数のリストを纏める場合に使えます。
>>> map(lambda a,b: (a,b), [1,2,3], [4,5,6]) [(1, 4), (2, 5), (3, 6)] >>> map(None, [1,2,3], [4,5,6]) # 短く書ける [(1, 4), (2, 5), (3, 6)]
これは zip とよく似た動作になりますが、zip は短いリストに、map は長いリストに合わせられるという点が異なります。
>>> zip([1,2], [1,2,3,4]) [(1, 1), (2, 2)] >>> map(None, [1,2], [1,2,3,4]) [(1, 1), (2, 2), (None, 3), (None, 4)]
None になるのが嫌な場合、以下のように書けばデフォルト値を入れることができます。
>>> map(lambda a,b: (a if a is not None else 0, ... b if b is not None else 0), ... [1,2], [1,2,3,4]) [(1, 1), (2, 2), (0, 3), (0, 4)]
ただし、リストの中に None が含まれていた場合はそれもデフォルト値になってしまいます。
>>> map(lambda a,b: (a if a is not None else 0, ... b if b is not None else 0), ... [1,2], [1,None,3,4]) [(1, 1), (2, 0), (0, 3), (0, 4)]
こういう場合は itertools.izip_longest を使うのがいいでしょう*2。
>>> from itertools import izip_longest >>> list(izip_longest([1,2], [1,None,3,4], fillvalue=0)) [(1, 1), (2, None), (0, 3), (0, 4)]
.
*1:大体、と付けたのは map の場合は lambda *args: args になるから
*2:Python3 なら zip_longest という名前らしい