Python 反復処理 #7 内包表記 #1

株式会社リュディアです。Python の内包表記についてまとめてみます。内包表記を身に着けると Python らしいコードを書けるようになります。

前回までの反復処理のまとめへのリンクは以下を参考にしてください。

内包表記はイテラブルなオブジェクトを生成する記述法の1つです。あるイテラブルなオブジェクト対し何らかの処理や操作を行った結果として別のイテラブルなオブジェクトを生成する場合に有用です。イテラブルなオブジェクトについては以下のまとめを参考にしてください。

では最初にイテラブルなオブジェクトとして range オブジェクトを使った具体例を見ながら進めていきます。以下の例を見てください。

l_squares = []
for i in range(5):
   l_squares.append(i**2)
print(l_squares)

>> [0, 1, 4, 9, 16]

空リスト l_squares を準備し、0 ~ 4 のループ処理中に各値の2乗の値のリストを生成する処理です。この方法で何の問題もありません。しかし内包表記を使うことでこの処理をコンパクトに記述することが可能です。以下の例を見てください。

l_squares = [i**2 for i in range(5)]
print(l_squares)

>> [0, 1, 4, 9, 16]

これが内包表記です。制御構造を持っていた for が1行で記述できています。表現が簡潔になりわかりやすくなっていますね。

次に以下の例を見てみましょう。

l_squares = []
for i in range(5):
   for j in range(5):
       l_squares.append(i**2 + j**3)
print(l_squares)

>> [0, 1, 8, 27, 64, 1, 2, 9, 28, 65, 4, 5, 12, 31, 68, 9, 10, 17, 36, 73, 16, 17, 24, 43, 80]

i, j を使って2重ループを構成しており、それぞれのループでの演算結果 i**2 + j**3 を新規リストの要素としています。この2重ループの記述を内包表記で書いてみましょう。

l_squares = [i**2 + j**3 for i in range(5) for j in range(5)]
print(l_squares)

>> [0, 1, 8, 27, 64, 1, 2, 9, 28, 65, 4, 5, 12, 31, 68, 9, 10, 17, 36, 73, 16, 17, 24, 43, 80]

2重ループについても特に問題ないですね。内包表記を前から順に見ていけば 2重ループの構成を理解できると思います。

最後にリストを使って2次元配列を扱う例をあげます。

l_2d = []
for i in range(5):
   l_1d = []
   for j in range(5):
       l_1d.append(i**2 + j**2)
   l_2d.append(l_1d)

print(l_2d)

>> [[0, 1, 4, 9, 16], [1, 2, 5, 10, 17], [4, 5, 8, 13, 20], [9, 10, 13, 18, 25], [16, 17, 20, 25, 32]]

図形的なイメージは以下のようになります。

画像1

内包表記で記載すると以下のようになります。i と j の場所に注意してコードを読んでみてください。

l_2d = [[i**2 + j **2 for j in range(5)] for i in range(5)]
print(l_2d)

>> [[0, 1, 4, 9, 16], [1, 2, 5, 10, 17], [4, 5, 8, 13, 20], [9, 10, 13, 18, 25], [16, 17, 20, 25, 32]]

内包表記は記述が簡潔になるのですが、複雑な内容を無理して書くと可読性が落ちてしまいます。三項演算子と同様、無理して記載せず記述が簡潔になりかつ可読性があがるような場合は適用する、ということでよいと思います。

反復処理に関するまとめの続きは以下からどうぞ。

では、ごきげんよう。


この記事が気に入ったらサポートをしてみませんか?