内包表記
内包表記とは
内包表記とは、Pythonでリストや辞書などのデータ構造を簡潔に生成するための構文です。繰り返し処理や条件分岐を使い、イテラブル(繰り返し可能なオブジェクト)から新しいデータ構造を生成します。
内包表記のメリット
リスト内包表記をすることのメリットは以下になります。
- 簡潔である
繰り返し構文で記述するよりも簡潔に記述することができます。
以下は0〜9までの数値を2乗した値を持つリストを作成する処理です。
squares = []
for x in range(10):
squares.append(x**2)
上記の処理を内包表記した場合は以下になります。
# [式 for 変数 in イテラブルオブジェクト]
squares = [x**2 for x in range(10)]
- 可読性が上がる
繰り返し処理よりも書き方が決まっている分、何をしているのかを理解することが容易になります。
- 処理効率が良い
for文のような繰り返し処理を行うよりも内包表記で記述した方が処理速度が向上します。
内包表記の書き方
リスト内包表記
以下が基本的なリストを生成する内包表記の書き方です。内包表記は最終的に作るものがリスト、辞書、集合のどれかによって記述方法が異なります。他の構文をリスト内包表記と比較して紹介するためにリスト内包表記だけ詳細に記述したいと思います。
# [式 for 繰り返し変数 in イテラブルオブジェクト]
squares = [x**2 for x in range(10)]
式
式の部分には基本的に何を書いてもよいです。イテラブル・・・繰り返し処理が可能なオブジェクトを利用した処理であるため、式の部分には、変数を使った演算や関数の呼び出しなどを記述します。例えば、x**2 で数値の2乗を計算したり、str(x) で文字列に変換することも可能です。この式の部分に記述したデータが左片の変数に格納されます。
繰り返し変数
for文に指定するような変数です。
イテラブルオブジェクト
リスト、辞書、rangeのような繰り返し可能なデータ構造を持った情報を指定します。
条件付きリスト内包表記
以下は条件付きのリスト内包表記の例です。リスト内包表記の後に「if 条件式」を追記します。
even = [x for x in range(10) if x % 2 == 0]
## 0,2,4,8
上記の例の場合、0を含む偶数だけがリストに格納されます。
辞書内包表記
以下は辞書を生成する内包表記です。
employee = [
{
"id" : 1,
"name" : "田中太郎"
},
{
"id" : 2,
"name" : "田中花子"
}
]
emp_dict = {emp.get('id'): emp for emp in employee}
# {1: {'id': 1, 'name': '田中太郎'},2: {'id':2,'name':'田中花子'}}
リスト内包表記と違う場所は以下の2点です。
- 「[]」ではなく「{}」で囲んでいること
- 辞書のkeyとvalueを設定するため、式の書き方が「key : value」になっている
集合内包表記
集合とは重複のないリストのことです。以下の構文で生成することができます。
unique_chars = {char.upper() for char in "Hello World"}
print(unique_chars)
# {'L', 'O', 'E', 'R', 'H', 'W', 'D'}
リスト内包表記との違いは以下になります
- 「[]」ではなく「{}」で囲っている
ネストしたリスト内包表記
2次元配列のようなネストした配列からもリスト内包表記でリストを生成するのに利用することができます。
matrix = [[1,2,3],[4,5,6],[7,8,9]]
# [式 for 繰り返し変数1 in イテラブルオブジェクト1 for 繰り返し変数2 in 繰り返し変数1]
nums = [num for row in matrix for num in row]
通常のリスト内包表記の後ろにさらにfor文で次の繰り返し処理を記述するように書くことができます。
もちろん、辞書内包表記と集合内包表記も同じようにfor文で続けることでネストした内包表記を記述することができます。
さいごに
私の第一プログラミング言語がJavaであったため、初めてPythonのリスト内包表記は混乱しました。可読性が上がるというのも疑問を持っていたと思います。
しかし、基本的にプログラマは命令の最小単位を1行で読んでいることに思い至りました。そう考えると1行で全ての処理内容と条件が表現されていると何をしているのかがわかりやすいのだと思いました。
処理内容も早く、記述方法から何が書かれているか推測しやすいなど有効に使うことでより優れたプログラムを書くことができると思いました。
ただし、あまりに複雑な処理を書くと逆に可読性が低下しそうですが、その場合には通常のfor文を利用することを検討しても良いでしょう。