4.5. リストのフィルター操作

知っての通り, Python にはリストの内包表記 (Section 3.6, “リストのマップ操作”) というリストを別のリストにマップする強力な構文があります. これにはフィルタリングの機能を付けられ, ある要素だけマップし, それ以外の要素はスキップするということができます.

以下がリストのフィルターの構文です.

[mapping-expression for element in source-list if filter-expression]

これはあなたが愛して止まないリストの内包表記の拡張です. 最初の 3 分の 2 は今までと同じで, 最後の if で始まる部分がフィルター式です. フィルター式は真偽値を返す式ならなんでも良いです (Python ではたいていのものは真偽値ですが). フィルター式が真を返す要素は全てマップ操作の対象になります. 他の要素は全て無視されるので, マップ式によって変換されることはなく, 出力リストにも含まれません.

Example 4.14. リストのフィルター操作の紹介

>>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
>>> [elem for elem in li if len(elem) > 1]       1
['mpilgrim', 'foo']
>>> [elem for elem in li if elem != "b"]         2
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1] 3
['a', 'mpilgrim', 'foo', 'c']
1 ここでのマップ式は単純 (単にそれぞれの要素の値を返すだけ) なので, フィルター式に注目しましょう. Python がリストを順々に辿り, それぞれの要素をフィルター式に通します. フィルター式が真になる場合は, その要素はマップされマップ式の結果が返り値のリストに入ります. ここでは, 1 文字のみの文字列を全てフィルターし, 1 文字よりも長い文字列のリストが得られます.
2 ここでは, 特定の値 b をフィルターしています. b が来るたびにフィルター式が偽になるので, その値が出てくるところ全てを除去していることに注意してください.
3 count は, リストの中にその値の現れる回数を返すリストのメソッドです. このフィルターはリストから重複を除去し, 元のリストの値をきっかり 1 つずつ持つリストを返す, とあなたは考えるかもしれませんが, そうではありません. なぜなら, 元のリストに 2 回現れる値 (この例では, bd) は完全に取り除かれるからです. リストから重複を取り除く方法はありますが, フィルタリングは解決法ではありません.

apihelper.py の以下の行に戻りましょう.

    methodList = [method for method in dir(object) if callable(getattr(object, method))]

これは見た目が複雑ですし, 実際にも複雑ですが, 基本的な構造は一緒です. フィルター式全体はリストを返し, それを methodList 変数に割り当てています. 式の最初の半分はリストのマップを行っている部分です. マップ式は恒等式になっていて, それぞれの要素の値を返します. dir(object)object の属性とメソッドのリスト -- あなたがマップしようとしているリスト -- を返します. よって, フィルター式の if 以降だけが新しい部分です.

フィルター式は恐しく見えますが, 実際はそうではありません. 既に callable, getattr, in について知っています. 前節で見たように, object がモジュールで method がそのモジュールの関数名のときに, 式 getattr(object, method) は関数オブジェクトを返します.

つまり, このフィルター式全体は (object という名前の) オブジェクトを受け取ります. そして, オブジェクトの属性, メソッド, 関数などの名前のリストを取得します. 次にリストをフィルターし, 余計なものを全て取り除きます. その除去を行うためにまず, 属性やメソッドや関数の名前から getattr 関数を使ってその実体への参照を取得しています. 次にそのオブジェクトが, (リストの pop のような) 組み込みメソッドおよび関数や (odbchelper モジュールの buildConnectionString 関数のような) ユーザが定義したメソッドおよび関数などの呼び出し可能なオブジェクトかどうかチェックします. 全てのモジュールに組み込まれている __name__ 属性のような他の属性はここでは取り扱いません.

リストのフィルター機能についてさらに知るには