Contents
1. 代入式とは何か
- 公式名称: Assignment expression(日本語では「代入式」)
- 俗称: walrus operator(英語圏)、セイウチ演算子(日本語圏)
:=の形がセイウチの目と牙に見えることから名付けられました。
例) 条件式の中で変数へ同時代入
python
if (n := len(data)) > 10:
print(f"要素数は {n} です")
公式ドキュメントは PEP 572 にて詳細が定義されています(PEP 572 – Assignment Expressions)。
主な特徴
- 式の中で代入できる → 冗長な二度書きを防止
- 可読性を保つために
:=が必須 → 代入が明示的になる - 単純代入のみ許容(リテラルや変数名への代入)で、アンパックや属性代入は不可
2. 背景 – PEP 572 とデザイン哲学
PEP 572 の目的は「式の中での代入による冗長削減と副作用の抑制」です。設計者は次の方針を掲げました。
- ステートメントと式の役割分担
=はステートメント専用、:=は明示的な式内代入に限定- シンプルさの保持
- 複雑なアンパックや属性代入は不可(例外:
if,while, 内包表記でのみ使用可)
この哲学に沿って実装すれば、コードベース全体の一貫性と保守性が高まります。
3. バージョン互換性と導入チェック
| Python バージョン | := の利用可否 |
|---|---|
| < 3.8 | ❌ SyntaxError |
| ≥ 3.8 | ✅ 利用可能 |
実装時のバージョン確認例
|
1 2 3 4 5 |
import sys if sys.version_info < (3, 8): raise RuntimeError("このコードは Python 3.8 以上が必要です") |
また、pyproject.toml の requires-python = ">=3.8" や setup.cfg の requires_python = >=3.8 といったメタデータで明示すれば、パッケージングツールや CI が自動的にチェックしてくれます。
4. 構文と基本的な使い方
4.1 if 文での代入式
|
1 2 3 4 |
a = [1, 2, 3, 4, 5] if (n := len(a)) > 3: print(f"リストは {n} 要素あり、閾値を超えています") |
- 利点:
len(a)を二度呼び出す必要がなくなる → 計算コスト削減・可読性向上
4.2 while ループでのカウンタ更新
|
1 2 3 4 5 6 |
with open('log.txt') as f: while (line := f.readline()): if line.startswith('#'): continue process(line) |
- 利点: 読み込みと判定が一行に集約でき、I/O 回数の削減につながる
4.3 リスト・ジェネレータ内包表記での活用
|
1 2 3 4 5 |
data = ['apple', 'banana', 'cherry'] # len(item) を二度評価しない例 result = [(l := len(item), l) for item in data] # → [(5, 5), (6, 6), (6, 6)] |
- 利点: 重い関数呼び出しや外部 API の結果を一度だけ取得して再利用できる
5. 実務で役立つ典型シーン
| シーン | コード例 | 効果 |
|---|---|---|
| I/O ループ データ取得と判定の同時実行 |
python\nwhile (chunk := read()) is not None:\n handle(chunk)\n |
呼び出し回数削減、コードが1行に集約 |
| 一時変数保持 DB からの取得結果を即判定 |
python\nif (user := get_user(42)) and user.is_active:\n print(f\"ユーザー {user.name} は有効\")\n |
高コスト処理の結果を再利用、余計な変数宣言が不要 |
| 内包表記での二重評価防止 外部 API 呼び出し例 |
python\nitems = fetch_items()\nsizes = [(s := heavy_calc(item)) for item in items if s > 10]\n |
重い計算を1回に抑え、可読性も保つ |
上記はすべて 「計算結果の再利用 + 条件評価」 が同時にできる典型例です。
詳細な解説は Zenn の記事でも紹介されています(Zenn – walrus operator の実践活用)。
6. パフォーマンスと可読性のトレードオフ、アンチパターン
6.1 PEP 8/PEP 572 が推奨するスタイル
- 必要な場合に限定して代入式を使う
- 長すぎる式は避ける(一行が複数の代入や論理演算で埋め尽くされないように)
良い例
|
1 2 3 |
if (cnt := count_items()) > 0: print(cnt) |
悪い例(アンチパターン)
|
1 2 3 4 |
# 複数代入が混在し、可読性が大幅に低下 if ((a := func1(x)) and (b := func2(a)) and (c := func3(b))) > 0: … |
6.2 長い式はステートメントへ分割するのが安全
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 改善前(長すぎる代入式) if (data := fetch()) and (valid := validate(data)) and (res := process(valid)): handle(res) # 改善後(明示的に分割) data = fetch() if not data: return valid = validate(data) if not valid: return res = process(valid) handle(res) |
- メリット: デバッグが容易、IDE の補完やリントツールの警告が減少
7. まとめ
- 正式名称は「代入式(Assignment expression)」、俗称は walrus operator/セイウチ演算子。
- Python 3.8 以降で利用可能。
sys.version_infoやrequires-pythonフィールドでバージョンチェックを必ず行うこと。 if,while, 内包表記などで 計算結果の再利用とコード簡潔化 が実現できる。- 典型的な活用シーンは
- I/O ループ (
while (chunk := read()) is not None:) - 高コスト取得の即判定 (
if (user := get_user(id)) and user.is_active:) - 重い関数呼び出しの二重評価防止(内包表記)
- 可読性は最優先。PEP 8/PEP 572 のガイドラインに沿い、式が長くなりすぎないよう意識することがベストプラクティスです。
これらのポイントを踏まえて、実務コードで安全かつ効果的に := 演算子を活用してください。