Python内包表記:ステップバイステップ入門 - Pythonチートシート

List Comprehensions は、他のリストからリストを作成するための特殊な構文です(Wikipedia、The Python Tutorial)。これらは、数値や、1 つまたは 2 つのレベルのネストされた for loops を扱う場合に非常に役立ちますが、それ以上になると、読みにくくなりすぎる可能性があります。
この記事では、いくつかの For Loops を作成し、それらを段階的に Comprehensions に書き直していきます。
基本
実際には、List Comprehensions はそれほど複雑ではありませんが、最初は少し奇妙に見えるため、理解するのがまだ少し難しいです。なぜでしょうか?それは、記述される順序が、通常 For Loop で見る順序と逆になっているからです。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> for n in names:
... print(n)
# Charles
# Susan
# Patrick
# George
# Carol
これを List Comprehension で行うには、loop の一番最後から始めます。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [print(n) for n in names]
# Charles
# Susan
# Patrick
# George
# Carol
順序が反転していることに注目してください。
- 最初に、ループの結果がどうなるか
[print(n) ...]。 - 次に、各アイテムを格納する変数を定義し、作業対象となる
List、Set、またはDictionaryを指し示します[... for n in names]。
内包表記で新しいリストを作る
これは List Comprehension の主な用途です。他の用途は、あなたや他の人にとって読みにくいコードになる可能性があります。
For Loop を使用して既存のコレクションから新しいリストを作成する方法は次のとおりです。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
そして、List Comprehension で同じことを行う方法は次のとおりです。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names]
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
これが可能な理由は、List Comprehension の標準動作がリストを返すことだからです。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [n for n in names]
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
条件を追加する
もし new_list に ‘C’ で始まる名前だけを含めたい場合はどうでしょうか?For Loop では、次のように行います。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... if n.startswith('C'):
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Carol']
List Comprehension では、if ステートメントを末尾に追加します。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C')]
>>> print(new_list)
# ['Charles', 'Carol']
ずっと読みやすくなります。
長いリスト内包表記を整形する
今回は、new_list に ‘C’ で始まる名前だけでなく、‘e’ で終わる名前や ‘k’ を含む名前も含まれるようにしたいとします。
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C') or n.endswith('e') or 'k' in n]
>>> print(new_list)
# ['Charles', 'Patrick', 'George', 'Carol']
これはかなり煩雑です。幸いなことに、Comprehensions を異なる行に分割することが可能です。
new_list = [
n
for n in names
if n.startswith("C")
or n.endswith("e")
or "k" in n
]
Set と Dict の内包表記
List Comprehensions の基本を学んだなら…おめでとうございます!あなたはそれを Sets と Dictionaries でも行ったことになります。
Set 内包表記
>>> my_set = {"abc", "def"}
>>> # ここでは、for loop を使って大文字の要素を持つ新しいセットを作成します
>>> new_set = set()
>>> for s in my_set:
... new_set.add(s.upper())
>>> print(new_set)
# {'DEF', 'ABC'}
>>> # 同じことを、set comprehension で行います
>>> new_set = {s.upper() for s in my_set}
>>> print(new_set)
# {'DEF', 'ABC'}
Dict 内包表記
>>> my_dict = {'name': 'Christine', 'age': 98}
>>> # for loop を使って既存の辞書から新しい辞書を作成します
>>> new_dict = {}
>>> for key, value in my_dict.items():
... new_dict[key] = value
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
# dict comprehension を使用
>>> new_dict = {key: value for key, value in my_dict.items()} # ":" に注目
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
まとめ
新しいことを学ぶたびに、それをすぐに使いたいという衝動に駆られます。そうなったとき、私は立ち止まって一瞬考えるように自分に言い聞かせます… この大きく、ネストされ、すでに煩雑に見える For Loop を List Comprehension に変更すべきでしょうか?おそらくそうではありません。
可読性は重要です。The Zen of Python.