コラム

【技術情報配信】(続々)Python Tips

お疲れ様です。

近頃はAIにコードを書かせたりレビューさせたりする機会も増えてきましたが、
出力されたコードが「妙にPythonらしいな」と感じることってありませんか?

前回・前々回では enumerate() と zip() を紹介しましたが、
今回の「リスト内包表記(List Comprehension)」が加わると、
一気に“Pythonらしい書き方”の幅が広がります。

1. 基本例:forループ + 条件分岐 + 加工
「数字のリストから偶数だけ取り出して、2乗したリストを作りたい」という処理です。

[従来の書き方(CやJavaスタイル)]
numbers = [1, 2, 3, 4, 5, 6]
even_squares = []

for n in numbers:
if n % 2 == 0:
even_squares.append(n ** 2)

print(even_squares) # [4, 16, 36]

空のリストを作って、
for で要素を取り出して、
if で偶数判定して、
append して。。。という流れですね。

これをリスト内包表記で書くとこうなります。

[リスト内包表記]
numbers = [1, 2, 3, 4, 5, 6]
even_squares = [n ** 2 for n in numbers if n % 2 == 0]

print(even_squares) # [4, 16, 36]

[ 式(生成したい値) for 要素 in イテラブル if 条件 ]
こんな形で書けます。
「空リストを作って append していく」という手続きをなくして、
“どんなリストを作りたいか” をそのまま書くイメージです。

2. 高度な例①:多重ループ(2次元リストの平坦化)
ネストされた2次元リスト(行列など)を1次元に崩す処理です。

[従来の書き方]
matrix = [[1, 2], [3, 4], [5, 6]]
flat = []

for row in matrix:
for item in row:
flat.append(item)

print(flat) # [1, 2, 3, 4, 5, 6]

[リスト内包表記]
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [item for row in matrix for item in row]

print(flat) # [1, 2, 3, 4, 5, 6]

多重ループもこの通り、1行で書けます。

3. 高度な例②:zip() や enumerate() との融合
前回、前々回の内容と組み合わせるとさらに便利になります。
例えば「ユーザー名とスコアのリストから、70点以上だけ辞書データにする」処理です。

[従来の書き方]
names = [“Apollo”, “Bacchus”, “Ceres”, “Diana”]
scores = [85, 50, 78, 90]

passed_users = []
for name, score in zip(names, scores):
if score >= 70:
passed_users.append({“name”: name, “score”: score})

print(passed_users)
# [{‘name’: ‘Apollo’, ‘score’: 85}, {‘name’: ‘Ceres’, ‘score’: 78}, {‘name’: ‘Diana’, ‘score’: 90}]

[リスト内包表記 + zip()]
names = [“Apollo”, “Bacchus”, “Ceres”, “Diana”]
scores = [85, 50, 78, 90]

# zip() と組み合わせて70点以上のユーザーだけを抽出・構造化
passed_users = [
{“name”: name, “score”: score}
for name, score in zip(names, scores)
if score >= 70
]

print(passed_users)
# [{‘name’: ‘Apollo’, ‘score’: 85}, {‘name’: ‘Ceres’, ‘score’: 78}, {‘name’: ‘Diana’, ‘score’: 90}]

「空リストを用意して、条件判定して、要素を加工して、append する」という一連の手続きが、
まるごと1つの記述に整理されてます。

【補足と注意点】
・内包表記は CPython が最適化しているため、append を繰り返すより高速になることが多いです。
・便利だからといって条件を詰め込みすぎると、難解コードになります。
 「パッと見で意図が伝わる範囲(1~2行程度)」に留めるのがよいです。

最初は「なんだこれ?」と思うかもしれませんが、
使っていくうちにすぐ慣れます。
そして手放せなくなります。

言語仕様を活かして、読みやすく安全なコードを書いていきましょう。
Pythonicなスタイルを一緒に磨いていければと思います。

— おまけ —
今回は「リスト」の内包表記を紹介しましたが、
括弧の形を変えれば「辞書(dict)」や「集合(set)」でも同じように使えます。

# 辞書内包表記の例(キーと値を反転させた辞書を作る)
user_scores = {“Apollo”: 85, “Ceres”: 78}
swapped = {score: name for name, score in user_scores.items()}

print(swapped) # {85: ‘Apollo’, 78: ‘Ceres’}

辞書の組み換えでよく使います。
※値が重複する場合は後勝ちで上書きされるので注意。

※ I’m no Python expert, but let’s all do our best to write Pythonic code!

以上。