blog

Pythonのリスト導出について話す

Luciano Ramalho氏は、文字列をUnicodeコードのリストに変換する例を示しました。 この書き方でまず印象的なのは、そのシンプルさです。 Python3では、式の中の変数や代入はローカル...

Jun 20, 2020 · 4 min. read
シェア

例題より

ルチアーノ・ラマーリョは、文字列をユニコード・リストに変換する例を示しました。

伝統的な書き方はこうです:

symbols='@#$%^&'
codes=[]
for symbol in symbols:
 codes.append(ord(symbol))

走行結果

INFO - codes -> [64, 35, 36, 37, 94, 38]

ord() 関数は chr() や unichr() 関数のコンパニオン関数で、引数として文字を受け取り、対応する ASCII 値、または Unicode 値を返します。

そしてリストの導出は次のように書きます:

codes=[ord(symbol) for symbol in symbols]

この文体の第一印象は簡潔さ。

リスト導出の使用原則: リスト導出は新しいリストを作成する場合にのみ使用し、できるだけシンプルに保つようにしてください。リストの導出に2行以上のコードが必要な場合は、forループによるリファクタリングを検討してください。

ローカルスコープ

Python3 では、式の中の変数や代入は局所的にしか働きません。したがって、それらは同じ名前の外側の変数には影響しません。

x='ABC'
dummy=[ord(x) for x in x]
logging.info('x -> %s',x)
logging.info('dummy -> %s',dummy)

走行結果

INFO - x -> ABC
INFO - dummy -> [65, 66, 67]

リスト導出とマップ/フィルタの組み合わせの比較

filter()

Python の filter() 関数はシーケンスにフィルタをかけるために使われ、条件にマッチしない要素をフィルタリングして、マッチする要素の新しいリストを返します。

のための文法:

filter(function, iterable)

この関数は2つの引数を取ります。1つ目は関数、2つ目はシーケンスで、シーケンスの各要素を関数の引数として渡して判定を行い、TrueかFalseを返し、最後にTrueを返した要素を新しいリストに入れます。

map()

そして map() は、指定された関数に従って指定されたシーケンスをマップします。

最初の引数 function は、引数シーケンスの各要素で関数 function を呼び出し、関数 function の各呼び出しによって返された値を含む新しいリストを返します。

比較

リスト導出とマップ/フィルタの組み合わせの記述の違いを比較するために、例を使用します。例えば、文字列をascii配列に変換し、コード値が38未満の値をフィルタリングする必要があるとします。

マップとフィルタの組み合わせ:

list(filter(lambda c:c>37,map(ord,symbols)))

リスト派生アプローチ:

[ord(s) for s in symbols if ord(s)>37]

比較すると、リスト導出の方が読みやすいことがわかります。

デカルト積の計算

直積とは、2つの集合XとYの直積のことで、数学ではX×Yと表記します。

ルチアーノ・ラマーリョはトランプの例でデカルト積とは何かを説明しました。4つのスートと3つのカードの表からなるリストのデカルト積は、12個の要素からなるリストになります。

Tシャツのサイズが3種類あり、それぞれ2色あるとすると、サイズと色の直積は6通りの組み合わせになります。

colors=['black','white']
sizes=['S','M','L']
# 色の次にサイズ
tshirts=[(color,size) for color in colors for size in sizes]
logging.info('tshirts -> %s',tshirts)
# サイズの次に色
tshirts=[(color,size) for size in sizes for color in colors]
logging.info('tshirts -> %s',tshirts)

走行結果

INFO - tshirts -> [('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'), ('white', 'M'), ('white', 'L')]
INFO - tshirts -> [('black', 'S'), ('white', 'S'), ('black', 'M'), ('white', 'M'), ('black', 'L'), ('white', 'L')]

for color in colors for size in sizes for size in sizes for color in colors は、まず色でソートし、次にサイズでソートすることを意味し、 while は、まずサイズでソートし、次に色でソートすることを意味します。

二重反復の順序も出力に影響します:

for color in colors:
 for size in sizes:
 logging.info('(color,size) -> %s',(color,size))
logging.info('
')
for size in sizes:
 for color in colors:
 logging.info('(color,size) -> %s',(color,size))

走行結果

INFO - (color,size) -> ('black', 'S')
INFO - (color,size) -> ('black', 'M')
INFO - (color,size) -> ('black', 'L')
INFO - (color,size) -> ('white', 'S')
INFO - (color,size) -> ('white', 'M')
INFO - (color,size) -> ('white', 'L')
INFO - 
INFO - (color,size) -> ('black', 'S')
INFO - (color,size) -> ('white', 'S')
INFO - (color,size) -> ('black', 'M')
INFO - (color,size) -> ('white', 'M')
INFO - (color,size) -> ('black', 'L')
INFO - (color,size) -> ('white', 'L')
Read next

効果的なJavaでのオブジェクトの作成と破棄

オブジェクトの作成と破棄\nこの記事は Effective java を読んで書かれました。\nコンストラクタ・メソッドの代わりに最初の静的ファクトリ\nいくつかの利点があります:\n1. 静的ファクトリーには名前があり、クライアント側のコードをより簡単に認識できます。\n2. 呼び出されるたびに新しいオブジェクトを作成する必要がありません。

Jun 19, 2020 · 3 min read