3.6. リストのマップ操作

Python の最も強力な特徴の 1 つはリストの内包表記であり, それを使うと, あるリストの個々の要素にある関数を適用して別のリストに変換する操作が簡潔に行えます.

Example 3.24. リストの内包表記の紹介

>>> li = [1, 9, 8, 4]
>>> [elem*2 for elem in li]      1
[2, 18, 16, 8]
>>> li                           2
[1, 9, 8, 4]
>>> li = [elem*2 for elem in li] 3
>>> li
[2, 18, 16, 8]
1 これを理解するためには, 右から左に眺めてください. li はマップ操作を行おうとしているリストです. Pythonli の要素を 1 つずつ順に辿り, それぞれの要素の値を一時的に変数 elem に割り当てます. 次に, Python は関数 elem*2 を適用し, その結果を返り値となるリストに追加します.
2 リストの内包表記は元のリストを変更しないことに注意してください.
3 リストの内包表記の結果を元の変数に割り当てるのは安全な操作です. Python はメモリ内に新しいリストを作り, リストの内包表記が計算し終わったら, その結果を変数に割り当てます.

以下は2 章で宣言した buildConnectionString 関数の中のリストの内包表記です.

["%s=%s" % (k, v) for k, v in params.items()]

まず, params 辞書の items 関数を呼んでいることに注目してください. この関数は辞書の全てのデータをタプルのリストにして返します.

Example 3.25. keys 関数, values 関数, items 関数

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.keys()   1
['server', 'uid', 'database', 'pwd']
>>> params.values() 2
['mpilgrim', 'sa', 'master', 'secret']
>>> params.items()  3
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
1 辞書の keys メソッドは全てのキーのリストを返します. そのリストは辞書が定義されたときの順序に従っているわけではない (辞書の要素は順序付けられていないことを思い出してください) のですが, ともかくリストです.
2 values メソッドは全ての値のリストを返します. そのリストは, keys メソッドで返されるリストと同じ順序になっています. なので, params.values()[n] == params[params.keys()[n]] が全ての値 n で成り立ちます.
3 items メソッドは (key, value) という形式のタプルのリストを返します. リストは辞書の全てのデータを含んでいます.

さて, buildConnectionString 関数が何をしているか見てみましょう. リスト params.items() を引数に取り, それぞれの要素をフォーマット文字列にはめて新しいリストを作っています. 新しいリストは params.items() と同じ数の要素を持っていますが, それぞれの要素は params 辞書のキーとそれに結び付いた値を含む文字列になります.

Example 3.26. buildConnectionString 関数のリストの内包表記を一歩々々

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> params.items()
[('server', 'mpilgrim'), ('uid', 'sa'), ('database', 'master'), ('pwd', 'secret')]
>>> [k for k, v in params.items()]                1
['server', 'uid', 'database', 'pwd']
>>> [v for k, v in params.items()]                2
['mpilgrim', 'sa', 'master', 'secret']
>>> ["%s=%s" % (k, v) for k, v in params.items()] 3
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
1 params.items() リストを反復するのに 2 つの変数を使っていることに注意してください. これは複数変数割り当てのもう 1 つの使い方です. params.items() の 1 番目の要素は ('server', 'mpilgrim') なので, リストの内包表記の 1 回目の反復では, k には 'server' が割り当てられ v には 'mpilgrim' が割り当てられます. この例では, v の値は無視し, k の値だけを返り値のリストに含めているので, リストの内包表記は params.keys() と同等の結果になります.
2 ここでも同じことをしていますが, k の値を無視しているので, このリストの内包表記は params.values() と同等の結果になります.
3 前の 2 つの例を簡単なフォーマット文字列を使って組み合わせると, 辞書の要素のキーも値も含んだ文字列のリストが得られます. これはいやにあのプログラムの出力に似ています. 後はこのリストの要素を 1 つの文字列につなぎ合わせるだけです.

リストの内包表記についてさらに知るには