プログラミングを行っていると、「この時点での変数は必ず正の値であるはず」「リストの中身は空ではないはず」といった、**「プログラムが正しく動作していれば絶対に成り立つはずの前提条件」**が存在します。
この前提条件をコードの中に記述し、もし満たされていない場合(バグがある場合)に即座にエラーを出して停止させる仕組みを**「アサーション(Assertion / 表明)」**と呼びます。Pythonでは assert 文を使ってこれを実現します。
この記事では、assert 文の基本的な使い方と、例外処理(raise)との決定的な違い、そして運用時の注意点について解説します。
assert 文の基本構文
assert 文は、条件式を評価し、それが True であれば何もせず処理を続行し、False であれば AssertionError という例外を発生させてプログラムを停止させます。
構文:
assert 条件式, "エラーメッセージ(省略可)"
具体的な使用例:計算ロジックの妥当性確認
例として、商品の定価と割引額から、最終的な支払額を計算する関数を作成します。 この計算において、「支払額がマイナスになる」ということは、ロジック上あり得ない(あってはならないバグ)と想定します。
def calculate_payment(price, discount):
"""
定価と割引額から支払額を計算する関数
"""
# 複雑な計算ロジックがあったと仮定
payment = price - discount
# アサーション: 支払額は必ず0以上であるはず
# もしマイナスなら、計算ロジックか入力前提にバグがある
assert payment >= 0, f"計算ロジックエラー: 支払額が負の値({payment})になっています。"
return payment
# --- 実行テスト ---
print("ケース1: 正常な計算")
result = calculate_payment(1000, 300)
print(f"支払額: {result}円")
print("\nケース2: バグを想定した計算(割引額が定価を超えている)")
# ここで AssertionError が発生し、バグの存在を知らせる
calculate_payment(1000, 1500)
実行結果:
ケース1: 正常な計算
支払額: 700円
ケース2: バグを想定した計算(割引額が定価を超えている)
Traceback (most recent call last):
...
AssertionError: 計算ロジックエラー: 支払額が負の値(-500)になっています。
assert 文を入れることで、開発中に想定外の状態(支払額がマイナス)になった瞬間にプログラムが停止し、原因の特定が容易になります。
assert と raise(例外処理)の使い分け
初心者が迷いやすいのが、「if 文でチェックして raise で例外を投げる」のと何が違うのか、という点です。
raise(例外処理): ユーザーの入力ミスやファイルの欠損など、**「実行時に起こりうるエラー」**への対処に使います。これらは製品としてリリースした後も機能する必要があります。assert(アサーション): プログラム自体のバグ、つまり**「開発者が絶対に起こらないと想定していること」**のチェックに使います。あくまで「開発者のためのデバッグツール」です。
最適化オプション (-O) による無効化
assert 文の最大の特徴は、Pythonを「最適化モード(-O オプション)」で実行した際に、完全に無視(削除)されることです。
ターミナルで以下のように実行すると、assert 文は実行されません。
python -O script.py
そのため、ユーザー入力のチェックやデータのバリデーション(妥当性確認)のような、本番環境でも必ず実行されなければならない処理に assert を使ってはいけません。
悪い例:
def register_user(age):
# ユーザー入力のチェックに assert を使ってはいけない
# python -O で実行されると、このチェックは消滅し、不正なデータが登録されてしまう
assert age >= 18, "未成年は登録できません"
...
良い例:
def register_user(age):
# 必須のチェックには必ず if と raise を使う
if age < 18:
raise ValueError("未成年は登録できません")
...
まとめ
assert 条件, メッセージで、前提条件が満たされているか(バグがないか)をチェックします。- 条件が
Falseの場合、AssertionErrorが発生します。 - 主に開発中のデバッグや、内部ロジックの整合性確認に使用します。
- Pythonの最適化オプション(
-O)で無効化されるため、必須の入力チェックや業務ロジックの制御には使用せず、if文とraiseを使用してください。
