Pythonコードの改善:アンチパターンから学ぶ、より読みやすく効率的な記述方法(Pythonic)

Pythonには「Pythonic(パイソニック)」と呼ばれる、Python特有の機能や慣習を活かした「推奨される書き方」が存在します。他のプログラミング言語の癖をそのまま持ち込んだり、冗長な記述を続けたりすることは「アンチパターン」と呼ばれ、可読性や保守性を下げる原因となります。

この記事では、よく見られるアンチパターンと、それを改善したコード例を対比形式で紹介します。

目次

1. 連続した比較演算子を使う

数値が特定の範囲内にあるかどうかを判定する際、and を使って式を連結する必要はありません。

アンチパターン:

age = 25
# 他の言語では一般的だが、Pythonでは冗長
if 18 <= age and age < 60:
    print("現役世代です")

改善後: 数学の不等式のように、比較演算子を連結して記述できます。

Python

age = 25
# 直感的で読みやすい
if 18 <= age < 60:
    print("現役世代です")

2. 複数の値との一致判定には in を使う

ある変数が、複数の候補のいずれかと一致するかを調べる際、or で繋ぐのは非効率です。

アンチパターン:

role = "editor"
if role == "admin" or role == "editor" or role == "moderator":
    print("管理画面にアクセス可能です")

改善後: タプルやセットと in 演算子を使うことで、条件を簡潔にまとめられます。

Python

role = "editor"
# 候補をタプルにまとめる
if role in ("admin", "editor", "moderator"):
    print("管理画面にアクセス可能です")

3. True/False の判定(真偽値判定)

ブール値や、リストの空/非空を判定する際、== Truelen() > 0 と書く必要はありません。

アンチパターン:

is_valid = True
user_list = ["user1"]

if is_valid == True:
    print("有効です")

if len(user_list) > 0:
    print("ユーザーが存在します")

改善後: Pythonでは、条件式に変数を直接記述すると、自動的に真偽値として評価されます(PEP 8推奨)。

  • True, 0以外の数値, 空でないコンテナ → True
  • False, None, 0, 空のコンテナ([], "", {}) → False
is_valid = True
user_list = ["user1"]

if is_valid:
    print("有効です")

if user_list:
    print("ユーザーが存在します")

4. 三項演算子の活用(条件式)

単純な条件分岐で変数に値を代入する場合、if-else ブロックを広げるとコードが縦に長くなります。

アンチパターン:

score = 85
result = ""
if score >= 80:
    result = "Pass"
else:
    result = "Fail"

改善後: 条件式(三項演算子)を使うことで、1行で記述できます。

score = 85
result = "Pass" if score >= 80 else "Fail"

5. シーケンスのループにカウンタ変数は不要

リストの要素にアクセスするために、len()range() でインデックス(カウンタ)を生成するのは、Pythonでは推奨されません。

アンチパターン:

fruits = ["Apple", "Banana", "Cherry"]
# インデックスを使って要素にアクセスする C言語スタイル
for i in range(len(fruits)):
    print(fruits[i])

改善後: for 文にリストを直接渡せば、要素を先頭から順に取り出せます。

fruits = ["Apple", "Banana", "Cherry"]
# 要素を直接取り出す
for fruit in fruits:
    print(fruit)

6. 同じ値なら同時に代入する

複数の変数を同じ初期値で初期化する場合、行を分ける必要はありません。

アンチパターン:

x = 0
y = 0
z = 0

改善後: = を繋げることで、一度に初期化できます。

x = y = z = 0

7. リスト内包表記の活用

既存のリストから新しいリストを作成する際、空のリストを作って append を繰り返すのは冗長であり、処理速度もやや劣ります。

アンチパターン:

numbers = [1, 2, 3, 4, 5]
squared_numbers = []
for n in numbers:
    squared_numbers.append(n ** 2)

改善後: リスト内包表記を使うことで、簡潔かつ高速に記述できます。

numbers = [1, 2, 3, 4, 5]
squared_numbers = [n ** 2 for n in numbers]

8. グローバルな名前(組み込み関数名)の上書きに注意する

変数名に list, str, sum, id などの組み込み関数名を使用すると、本来の機能が使えなくなります(シャドーイング)。

アンチパターン:

# 'list' という変数名は避けるべき
list = [10, 20, 30]

# 本来の list() 関数が使えなくなり、エラーになる
# new_list = list((1, 2)) 
# TypeError: 'list' object is not callable

改善後: 意味のある変数名、あるいは型名と被らない変数名を使用します。

number_list = [10, 20, 30]
# 本来の機能は維持される
new_list = list((1, 2)) 

9. 変数の値の入れ替えは一時変数不要

変数の値を交換(スワップ)するために、一時変数(temp)を用意する必要はありません。

アンチパターン:

a = 100
b = 200

temp = a
a = b
b = temp

改善後: Pythonのタプルアンパックを利用すれば、1行でスマートに入れ替えが可能です。

a = 100
b = 200

a, b = b, a

まとめ

これらの書き方は、単にコードを短くするだけでなく、意図を明確にし、バグを減らす効果があります。

  • 比較は連結する。
  • 複数の候補は in でまとめる。
  • 真偽値判定はシンプルに。
  • ループは直接イテラブルを回す。
  • 内包表記やアンパックを活用する。
  • 組み込み関数名を変数名にしない。

これらを意識して、Pythonicなコードを目指してください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次