プログラミングをしていると、「あれ?」と思わず感心する瞬間があります。複雑なロジックを驚くほど簡潔かつ優雅に処理するコード、まさに「Pythonic」と呼ばれるコードたちです。
今日は、私たちが一緒に感動した、シンプルでありながら強力な3つのPythonicコードスニペットを紹介します。
1. プレフィックススライス: '動的'な時に輝く真価
ファイルパスから基本パスを取り除き、相対パスだけを取得したいときに、len()と文字列スライシング(slicing)を組み合わせます。
# 例1
prefix = "/var/data/user/files"
p = "/var/data/user/files/report.txt"
if p.startswith(prefix):
relative_path = p[len(prefix):]
print(relative_path)
# /report.txt
ここまでのコードは、p[22:](数字22を直接書くこと)と変わらないように見えます。しかし、このコードの真の価値は、プレフィックスが動的に変化する時に明らかになります。
✅ The Pythonic Way (真価発揮)
複数のユーザのデータパスを処理する必要があると想像してみてください。
def get_relative_path(full_path, user_name):
# ⭐️ プレフィックスがuser_nameに応じて動的に変わります!
prefix = f"/var/data/{user_name}/files"
if full_path.startswith(prefix):
# len()が毎回正確な動的長さを計算します。
# user1の場合は22、long_userの場合は29...
return full_path[len(prefix):]
return full_path
# 'user1'(プレフィックス長さ22)
path1 = "/var/data/user1/files/report.txt"
print(f"user1: {get_relative_path(path1, 'user1')}")
# 'long_user_name_2'(プレフィックス長さ29)
path2 = "/var/data/long_user_name_2/files/document.pdf"
print(f"user2: {get_relative_path(path2, 'long_user_name_2')}")
結果:
user1: /report.txt
user2: /document.pdf
😲 感動ポイント
コードはプレフィックスの _内容_ や _固定長_ に依存していません。唯一、len()によってリアルタイムで計算された長さを基に[N:]スライシングを行うだけです。
これが、p[22:]のようなハードコーディングとは次元の異なるメンテナンス性が高く堅牢なコードです。
2. 一時変数なしの「魔法のスワップ」
二つの変数の値を入れ替えるとき、tempという一時変数は必要ありません。
✅ The Pythonic Way
a = 10
b = 20
# Python的なスワップ
a, b = b, a
print(f"a = {a}, b = {b}")
# a = 20, b = 10
😲 感動ポイント
これはタプルのパッキング(Packing)とアンパッキング(Unpacking)を利用したものです。
-
b, a: 等号右側の(20, 10)の値が一時タプルとして「パッキング」されます。 -
a, b = ...: このタプルの値が順番に左側のaとbの変数に「アンパッキング」(展開して代入)されます。
「aとbをbとaに入れ替える」という意図をコードにそのまま表現しています。
3. forループを1行で: 'コンプリヘンション'の魔法
「どんなデータを持ち、特定の条件に合った要素だけを選び出し、変形した後、新しいコレクションを作りたい。」
この長文がforループ4〜5行に翻訳されることがあります。Pythonはこのプロセスを1行に圧縮します。
辞書: KeyとValueを反転する
変数スワップの感動は辞書でも続きます。forループを使用してk:vをv:kに変える状況です。
# 従来の方法
my_dict = {'name': 'Alice', 'job': 'Engineer'}
inverted_dict = {}
for k, v in my_dict.items():
inverted_dict[v] = k
✅ The Pythonic Way (Dictionary Comprehension)
my_dict = {'name': 'Alice', 'job': 'Engineer'}
# "my_dictからk,vを抽出して、v:kのペアからなる新しいdictを作成する"
inverted_dict = {v: k for k, v in my_dict.items()}
print(inverted_dict)
# {'Alice': 'name', 'Engineer': 'job'}
(ただし、この方法はValueがユニークである必要があります。)
リスト: 条件に合った要素で新しいリストを作成する
この魔法はリストでより頻繁に使われます。0〜9の中から偶数だけを選んで、その平方のリストを作ってみましょう。
# 従来の方法
squares_of_evens = []
for i in range(10):
if i % 2 == 0:
squares_of_evens.append(i * i)
✅ The Pythonic Way (List Comprehension)
# "iを0~9までループし(for)、iが偶数なら(if)、i*iを(what)リストに作る"
squares_of_evens = [i * i for i in range(10) if i % 2 == 0]
print(squares_of_evens)
# [0, 4, 16, 36, 64]
😲 感動ポイント
コンプリヘンションは「どのように」作るか(how: 空のリスト宣言、ループ、append...)を冗長に説明する代わりに、「何を」欲しいのか(what)を定義するようにコードを変えてくれます。
結論: コードが感動を与える時
今日見た3つのスニペットは単なる「コーディングテクニック」ではありません。
これは「どうすればもっと明確に、もっと簡潔に、もっと美しく自分の意図を表現できるか?」というPythonの哲学(The Zen of Python)を示しています。
コードが単に機械のための命令を超え、開発者の思考を込めた『言葉』になること、そしてよく書かれた文章が感動を与えるように、よく書かれたコードも私たちに「えっ?」という感動を与えることができることを私たちに気づかせてくれます。
皆さんのコードにもこの「Pythonicな感動」がたくさんありますように。
コメントはありません。