mapを使うべきか、リスト内包表記を使うべきか

bonlifeです。Python使っていてよく悩むことがあるのでメモ。

この日記を見ていたら、リスト内包表記を使ってスッキリと10進数のIPアドレスを16進数に変換していました。私もよくリスト内包表記を使うんですけど、その時々のノリでmapを使ったりもします。ということで、一部にmapを使って書き換えてみました。ワンライナー的で可読性が低いかな。

In [1]: ip_address = '192.168.0.2'

In [2]: ''.join([ '%02x' % i for i in map(int,ip_address.split('.')) ])
Out[2]: 'c0a80002'

リスト内包表記の方が、ifでフィルタリングしたり、ネストした複雑な関数を適用したりできるの柔軟で便利だよ!的なことがこのあたりに書かれていましたが、mapなどなどを使うのは非推奨とか書かれているわけではないですよね。個人的には以下のようなノリで使い分けてます。

  1. フィルタリングが必要ならリスト内包表記
  2. ネストした関数の適用が必要な場合はリスト内包表記
  3. Unicodeとstrに対する処理はリスト内包表記
  4. どちらでも書けるケースで、1行が長くなりそうな場合map
  5. リスト内包表記がネストしそうな場合、内側ではmap

なんだかんだで基本はリスト内包表記でOKって結論ですね。mapを使わなければできないことがなさそうですし。
3点目についてコードで補足。(こんな風にUnicodeと普通の文字列が混ざるケースなんてないですけどね…。)

In [10]: L = ['a', 'b', u'c']

In [11]: [ x.upper() for x in L ]
Out[11]: ['A', 'B', u'C']

In [12]: "".join([ x.upper() for x in L ])
Out[12]: u'ABC'

ちなみに、元記事でstructモジュール使っているところは以下のように書くこともできますね。普段、%c なんて使いませんが、数値を指定すると16進数的なアレを返すのね。フーン。

In [3]: ''.join([ '%c' % i for i in map(int,ip_address.split('.')) ])
Out[3]: '\xc0\xa8\x00\x02'