Python速習ガイド - ステップ2 制御フロー (5) - ループ(3): 内包表記
- 本講座は、Pythonプログラミングの基礎を手を動かしながら最速で身につけるための講座です。
- 「スタイルガイド」では、Pythonできれいなコードを書くためのガイドライン(PEP8)で紹介されている内容を主に記載しています。
- 各コードは実行して結果を確認することができます。
ページの再読み込みで元の内容に戻りますので、自由にいじってみてください。
「ステップ2 制御フロー」の続きです。
2.2. ループ
2.2.3. 内包表記
内包表記(Comprehension) は、イテラブルなオブジェクトを簡単に作成するための構文です。
- 従来のループ処理を1行で表現できるため、コードが簡潔になります
for
文を使用した生成よりも一般的に高速に動作します
リスト内包表記
リスト内包表記(list comprehension)は、ループを使ってリストを生成する簡潔な構文です。
上記のリスト内包表記は、以下のfor
文と同じリストを生成します:
内包表記は以下のように条件を追加することも可能です
上記リストをfor
文を用いて作成するコードは以下のとおりです:
リスト内包表記は多重ループにも対応しています
下記for
文と同じリストを生成します:
多重ループの場合、for
の記述順は通常のネストされたfor
文と同じ順序で書く必要があります。
上の内包表記は、次のfor
文と同じ意味になります:
このように、外側のループ(for student in students_scores
)を先に書き、内側のループ(for score in student
)を後に書く必要があります。順序を逆にして for score in student for student in students_scores
のように書くと、student
が未定義の状態で使われるためエラーになります。
- 内包表記の記述が長くなる場合は複数行に分割しましょう
- 複雑すぎる内包表記は可読性が低下するため、従来のループの使用を検討しましょう
1 * 1 + 2 * 2 + ... + 100 * 100
の計算結果をリスト内包表記を使用して求めましょう。
解答例
1から20までの数のうち、3の倍数または5の倍数のリストをリスト内包表記で作成しましょう。
解答例
あるホテルの各階の空き部屋のリストは以下のとおりです。
vacant_rooms_by_floor = [
[101, 102, 103], # 1階の空き部屋
[202, 203], # 2階の空き部屋
[301, 303, 305] # 3階の空き部屋
]
- すべての空き部屋からなるリストを表示しましょう
- 末尾が1または5の部屋は角部屋です。空き部屋の内、角部屋のみのリストを表示しましょう
(ヒント: 末尾の数字は<部屋番号> % 10
で計算できます)
解答例
ベンチマークツールを用いて、リスト内包表記と通常ループの処理速度を比較してみます:
ベンチマーク結果より、ループより内包表記のほうが速いことがわかります。
辞書内包表記
辞書内包表記(dict comprehension)は、ループを使って簡潔に辞書を生成する構文です。
辞書内包表記を使って既存の辞書を変換することもできます:
学生の得点を記録した辞書があります。
- 合格(60点以上)した学生だけの辞書を作成しましょう
- 合格した各学生に対して、80点以上の場合は「優」それ以外は「良」という評価を対応させる辞書を作成しましょう (ヒント: 三項演算子を利用しましょう)
解答例
集合内包表記
集合内包表記(set comprehension)は、ループを使って簡潔に集合を生成する構文です。
ジェネレータ式
ジェネレータ式は、内包表記に似ていますが、結果を一度に生成するのではなく、必要に応じて一つずつ値を生成するオブジェクト(ジェネレータ)を返します。
- メモリ効率が良いため、大きなデータセットを扱う際に便利です。
- ただし、1度使用すると空になって使えなくなることに注意してください。
リスト内包表記の練習問題で扱った 1 * 1 + 2 * 2 + ... + 100 * 100
の計算を、
よりメモリ効率の良いジェネレータ式を用いて実行しましょう。
解答例
ベンチマークツールを用いて、実際にリスト内包表記とジェネレータ式のメモリ効率を比較してみます。
上記ベンチマーク結果より、ジェネレータ式の場合はサイズによらずメモリ使用量が少なく、
リスト内包表記の場合はサイズに比例してメモリ使用量が増加することがわかります。
内包表記まとめ
種類 | 構文 | 用途 | 主な特徴 |
---|---|---|---|
リスト内包表記 | [式 for 要素 in イテラブル if 条件] |
リスト作成 | リストを簡潔に生成 |
辞書内包表記 | {キー: 値 for 要素 in イテラブル if 条件} |
辞書作成 | 辞書を簡潔に生成 |
集合内包表記 | {式 for 要素 in イテラブル if 条件} |
集合作成 | 集合を簡潔に生成 |
ジェネレータ式 | (式 for 要素 in イテラブル if 条件) |
遅延評価 | メモリ効率がよい。一度限りの使用 |
- リスト内包表記は通常のループよりも一般的に高速に動作する
- 複雑すぎる条件式は可読性が低下するため、従来のループの使用を検討する
- 大量のデータを扱う場合は、ジェネレータ式を使うとメモリ使用量を抑えることができる