今日は、PythonでList Comprehensionを使う方法についてお話します。
リスト内包は一般的にコードを読みやすく、書きやすくするための構文上の糖分です。
リストを作成するコードを扱うとき、ネストしたループを何度も書くのは面倒なことがよくあります。
Pythonはこの機能を導入することで、これを容易にしています。
では、この機能をどのように使うか、適切な例を挙げて説明しましょう。
リストの基本構造理解
普通に書かれた次のコードを考えてみましょう。
word = "Hello from Python"
letters = []
for letter in word:
letters.append(letter)
print (letters)
|
結果は以下の通りです。
['H', 'e', 'l', 'l', 'o', ' ', 'f', 'r', 'o', 'm', ' ', 'A', 's', 'k', 'P', 'y', 't', 'h', 'o', 'n'] |
上記のコードは、単語の文字のリストを出力します。
リストの要素は文字であるという共通の性質を持っており、それらはリストに追加されるため、リスト理解を使ってこのコードを短くすることができます。
では、リスト理解を使って、このコードをもっと短く、読みやすくしてみましょう。
word = "Hello from Python"
letters = [letter for letter in word]
print (letters)
|
結果は以下の通りです。
['H', 'e', 'l', 'l', 'o', ' ', 'f', 'r', 'o', 'm', ' ', 'A', 's', 'k', 'P', 'y', 't', 'h', 'o', 'n'] |
どうです、簡単でしょう?コードの意図は明確です。
単語の文字を拾って、それを直接リストに追加しているのです。
さて、リスト内包は他のイテレータブルでも使うことができます。
別の例として、1から10までの数字の2乗を生成する方法を考えてみましょう。
通常のやり方は次のようになります。
squares = []
for i in range ( 1 , 11 ):
squares.append(i * i)
print (squares)
|
結果は以下の通りです。
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] |
これでも十分小さいのですが、リスト内包を使えばもっとうまくいきます。
これをたった2行のコードに減らすことができるのです。
squares = [i * i for i in range ( 1 , 11 )]
print (squares)
|
ここまでで、リスト内包の威力を実感していただけたと思います。
Using Conditions in the List Comprehension (リストで条件を使う)
リスト内包では、if
と else
という条件文を使うことができます。
ここでは、最初のケースとして if
条件のみを使用する場合を考えてみましょう。
このタイプのリスト内包の一般的な構造は以下の通りです。
list = [item for item in iterable if condition]
|
つまり、ここでは list
は condition
が True になる item
だけから構成されます。
先ほどの正方形を作る例で、 if
を使って偶数のみに制限してみましょう。
squares = [i * i for i in range ( 1 , 11 ) if i % 2 = = 0 ]
print (squares)
|
結果は以下の通りです。
[4, 16, 36, 64, 100] |
確かに、ここでは i が偶数のときだけ i % 2 == 0
となるので、偶数要素の正方形しか得られない。
次に、2番目のケースとして、else
条件もつけてみましょう。
今度は、次のような構造になります。
list = [value1 if condition else value2 for item in iterable]
|
ここで、リストは condition == True
ならば value1
の要素、 condition == False
ならば value2
の要素から構成されます。
ここで、i<=5
まで整数の正方形を表示し続ける例を見てみましょう。
もし i > 5 ならば、代わりに 0 を表示します。
リスト内包は次のようになります。
my_list = [i * i if i < = 5 else 0 for i in range ( 10 )]
print (my_list)
|
結果は以下の通りです。
[0, 1, 4, 9, 16, 25, 0, 0, 0, 0] |
見てわかるように、リストにはすべての数 <= 5 の二乗だけが含まれています。
他の条件式や、ラムダ関数も使うことができます。
以下は、ラムダ関数を使って、0からの連続した和を計算する、ちょっと変わった例です (0, 1 + 2, 2 + 3, 3 + 4… )
pair_sums = [( lambda x, y: x + y)(i, j) if i > 1 else 0 for i, j in zip ( range ( 1 , 11 ), range ( 0 , 10 ))]
print (pair_sums)
|
結果は以下の通りです。
[0, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
見てわかるように、このコードは最も読みやすいものとは言えません。
一度にたくさんのことをやろうとすると、リスト内包を使わないように気をつけましょう。
この方法は、単純なループ条件文を実行してリストを作成するときに使うもので、各要素に対して個別に数学的な計算を行いたいときには使わない方がよいでしょう。
まとめ
今回は、PythonのList Comprehensionセマンティクスの利用について学びました。
参考文献
- Pythonのリストに関するPythonの記事