【Python】Pythonの三項演算子とwalrus演算子(:=)の使い方をやさしく解説

Python

こんにちは、かつコーチです。

今回は、コードを短く読みやすくしてくれる2つの演算子、三項演算子walrus演算子(:=を解説します。

どちらも「知らなくても書けるが、知っていると一気にコードがスッキリする」タイプの構文です。

私も最初にこの2つを見たとき、「なぜわざわざif文を1行に押し込めるのか」「:=って何のための記号なのか」と疑問に思いました。

しかし実際に使ってみると、条件分岐や繰り返し処理を書くときの選択肢がぐっと広がることが分かりました。

この記事では、三項演算子の基本構文と、Python 3.8で追加された比較的新しい構文であるwalrus演算子の使いどころを、具体例とともに解説します。

三項演算子の基本

三項演算子とは

三項演算子とは、if文を1行で書くための構文で、正式には条件式(Conditional Expression)と呼びます。

通常のif文と、三項演算子で書いた場合を比較してみましょう。

# 通常のif文
age = 20
if age >= 18:
    status = "成人"
else:
    status = "未成年"

print(status)  # 成人
# 三項演算子
age = 20
status = "成人" if age >= 18 else "未成年"

print(status)  # 成人

三項演算子の構文は、次の形になります。

値A if 条件 else 値B

「条件が真(True)なら値A、そうでなければ値B」という意味になります。

if文を4行使っていた処理が、たった1行で表現できるようになりました。

三項演算子が向いているケース・向いていないケース

三項演算子は便利ですが、どんな場面でも使うべきというわけではありません。

向いているのは、「変数に値を代入するだけ」のシンプルな条件分岐です。

# 向いている例:シンプルな値の代入
discount = 0.1 if is_member else 0.0

一方、条件分岐の中でさらに複数の処理をしたい場合や、条件が複雑になる場合は、通常のif文を使った方が読みやすくなります。

# 向いていない例:無理に三項演算子でネストさせている
grade = "A" if score >= 90 else "B" if score >= 70 else "C" if score >= 50 else "D"

このように三項演算子を入れ子にすると、一見短くなりますが、パッと見て条件の構造が分かりにくくなります。

「1行で条件と値がすぐに読み取れるか」が、三項演算子を使うかどうかの判断基準になります。

walrus演算子(:=)の基本

walrus演算子とは

walrus演算子(:=とは、Python 3.8で追加された、代入と式の評価を同時に行う演算子です。

見た目がセイウチ(walrus)の目と牙に見えることから、この愛称が付いています。

まずは、walrus演算子を使わない場合のコードを見てみます。

import re

text = "価格は1500円です"
match = re.search(r"\d+", text)
if match:
    print(f"見つかった数字: {match.group()}")

この場合、match = re.search(...)という代入と、if match:という条件判定を、2行に分けて書く必要があります。

walrus演算子を使うと、この2行を1行にまとめられます。

import re

text = "価格は1500円です"
if (match := re.search(r"\d+", text)):
    print(f"見つかった数字: {match.group()}")

match := re.search(r"\d+", text)という部分で、「検索した結果をmatchに代入しつつ、その値をif文の条件としても使う」という2つの処理を同時に行っています。

なぜwalrus演算子が便利なのか

walrus演算子が便利なのは、「一度計算した値を、条件判定にも後続の処理にも使い回したい」ケースです。

例えば、リストの中から条件に合う値を探して使う処理を考えてみます。

# walrus演算子を使わない場合
numbers = [3, 8, 15, 22, 30]
result = [n for n in numbers if n > 10]
if len(result) > 0:
    print(f"10より大きい数: {result}")
# walrus演算子を使う場合
numbers = [3, 8, 15, 22, 30]
if (result := [n for n in numbers if n > 10]):
    print(f"10より大きい数: {result}")

計算結果を一時変数に入れてから条件判定する、という2段階の処理を1行にまとめられるため、コードの見通しがよくなる場面があります。

よくあるつまずきポイント・エラー対処

つまずき1:walrus演算子の括弧忘れ

walrus演算子を使うときに、初心者がよくつまずくのが括弧の付け忘れです。

❌ Before:括弧を付けずに書いてエラーになる

text = "価格は1500円です"
import re

if match := re.search(r"\d+", text):
    print(match.group())

実はこのコード自体は動くのですが、複数の条件を組み合わせようとすると問題が起こります。

if match := re.search(r"\d+", text) and len(text) > 0:
    print(match.group())
AttributeError: 'bool' object has no attribute 'group'

私はこのエラーに遭遇したとき、「matchにちゃんと検索結果が入っているはずなのに、なぜbool型扱いされるのか」と混乱しました。

原因は、演算子の優先順位にあります。

:=andより優先順位が低いため、match := (re.search(...) and len(text) > 0)という意味になってしまい、matchには検索結果ではなくTrue/Falseが代入されていたのです。

✅ After:括弧で囲んで優先順位を明示する

import re

text = "価格は1500円です"
if (match := re.search(r"\d+", text)) and len(text) > 0:
    print(match.group())  # 1500

(match := re.search(r"\d+", text))のように括弧で囲むことで、「先にこの代入式を評価する」という意図を明示できます。

walrus演算子を他の条件と組み合わせるときは、必ず括弧で囲むという習慣をつけておくと、このタイプのバグを防げます。

つまずき2:三項演算子で条件式の範囲を勘違いする

三項演算子でも、演算子の優先順位に関するつまずきがあります。

❌ Before:条件式の範囲を誤解して意図しない結果になる

price = 1000
discount_rate = 0.1 if price > 500 else 0.0
total = price * 1 - discount_rate

print(total)  # 999.9(意図した割引額になっていない)

このコードを書いた人は、「500円より高ければ10%引き」を意図していたかもしれません。

しかし、total = price * 1 - discount_rateという計算式には、割引「率」がそのまま金額として引き算されてしまっているというロジック自体の誤りがあります。

✅ After:計算のロジックを見直す

price = 1000
discount_rate = 0.1 if price > 500 else 0.0
total = price * (1 - discount_rate)

print(total)  # 900.0

三項演算子自体にバグがあったわけではなく、三項演算子で作った値を、その後どう計算に使うかでミスが起こりやすい、という点に注意が必要です。

三項演算子を使うときは、「結果の値が何を表しているのか(割引率なのか、割引後の金額なのか)」を意識してコードを書くと、この種のミスを防げます。

応用・一歩先の使い方

while文とwalrus演算子の組み合わせ

walrus演算子は、while文と組み合わせるとさらに真価を発揮します。

# walrus演算子を使わない場合
data = []
while True:
    chunk = input("データを入力(空文字で終了): ")
    if chunk == "":
        break
    data.append(chunk)
# walrus演算子を使う場合
data = []
while (chunk := input("データを入力(空文字で終了): ")) != "":
    data.append(chunk)

「入力を受け取りつつ、その場で終了条件を判定する」という処理が1行にまとまり、while Truebreakを使った書き方より意図が読み取りやすくなります。

リスト内包表記との組み合わせ

walrus演算子は、リスト内包表記の中で「同じ計算を2回行いたくない」場合にも使えます。

import math

numbers = [4, 9, 16, 25]

# walrus演算子を使わない場合(sqrtを2回計算している)
results = [math.sqrt(n) for n in numbers if math.sqrt(n) > 3]

# walrus演算子を使う場合(sqrtの計算を1回にまとめている)
results = [root for n in numbers if (root := math.sqrt(n)) > 3]

print(results)  # [4.0, 5.0]

同じ関数呼び出しを条件式と値の両方で使いたいとき、walrus演算子を使えば計算を1回にまとめられます。

処理速度だけでなく、コードの重複も減らせるため、地味に便利なテクニックです。

まとめ

この記事のポイント

  • 三項演算子は値A if 条件 else 値Bという構文で、シンプルな条件分岐を1行にまとめられる
  • 三項演算子の入れ子は読みにくくなりやすいため、複雑な条件は通常のif文を使う
  • walrus演算子(:=)はPython 3.8で追加され、代入と条件判定を同時に行える
  • walrus演算子を他の条件と組み合わせるときは、優先順位のトラブルを避けるため括弧で囲む
  • while文やリスト内包表記と組み合わせると、同じ計算の重複を減らせる

次に読むべき記事

条件式の書き方が分かったら、次はリスト内包表記の基本もあわせて押さえておきましょう。

→ 次の記事:Pythonのリスト内包表記の書き方と使いどころ

タグ: Python, 中級者向け, 基本文法

タイトルとURLをコピーしました