PR

【Python】assert(アサーション)を3分でわかりやすく解説

Python

Pythonの assert 文はプログラムが進行するにあたって、ある条件が必ず満たされていることを確認するために使われます。この文はテストやデバッグ時に特に役立ちます。

サンプル assert文

def apply_discount(product, discount):
    price = product.price * (1.0 - discount)
    assert 0 <= price <= product.price, "The discounted price cannot be negative or more than the original price."
    return price

このページではPythonにおけるassert文の使い方(そもそも、アサーションって何?)を1からわかりやすくサンプルコード付きで丁寧に解説します。

このページで学べる内容
  • アサーションとは?
  • assert文の使い方とコツ
  • assert文を利用する際の注意点

Pythonエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。

参考 Pythonの基本的な書き方・構文ルール

スポンサーリンク

Python:アサーション(assertion)とは

アサーション(assertion)とは、プログラムが特定の状態であることを確認するためのチェックのことを指します。アサーションは通常、プログラムが期待する状態や条件が満たされているかを確認するために使用されます。

わかりやすく言い換えると、コードが正しく機能するための前提条件を設定するものであり、その前提条件が満たされないとき(つまり、開発者にとって想定外の状況が生じたとき)に警告を発するものです。

具体例を考えてみましょう。

あなたが1つのWebアプリケーションを開発していて、このアプリケーションはユーザーから提供された年齢に基づいて特定の情報を提供する機能を有しているとします。しかし、通常「年齢」はマイナス値であるわけがないので、年齢は必ず0以上の数値でなければならない、という前提を置いていたとしてます。

このとき、この前提条件を保証するために利用するのがアサーションです。

def provide_information(age):
    assert age >= 0, "Age cannot be negative!"
    # 年齢に基づいて情報を提供するコード...

参考 def文(Pythonの関数)

この関数は、年齢が0以上であることを前提としています。assert age >= 0 というアサーションがこの前提条件をチェックしています。もし、何らかの理由で年齢がマイナスの値が関数に渡された場合、これは開発者の想定外の状況です。

その時点でアサーションは AssertionError を発生させ、"Age cannot be negative!" というメッセージを出力。これにより、開発者は直ちに問題を察知し、問題の原因を特定しやすくなるというわけです。

けど、実際わざわざアサーションを利用するメリットはあるのでしょうか?言い換えると、普通にエラーチェックを入れるだけではだめなのでしょうか・・・?

エラーチェックとアサーションの使い分けについて、具体的な例を用いて説明します。

エラーチェックとアサーション

エラーチェックとアサーションは異なる目的を持っています。

エラーチェックはユーザーや外部システムによる予期しない入力や振る舞いを処理し、アサーションは開発者がコードの振る舞いについて設定した前提条件を確認するために使用されます。

エラーチェック

エラーチェックは通常、ユーザーからの入力や外部システムからの応答など、プログラムのコントロールが難しい部分で行われます。例えば、ユーザーからの入力に対しては、その値が有効な範囲内にあることを確認するエラーチェックが必要になります。

def divide_numbers(numerator, denominator):
    if denominator == 0:
        raise ValueError("Denominator cannot be zero")
    return numerator / denominator

参考 if文 / 比較演算子

この例では、0で割るというエラーを防ぐためにエラーチェックを行っています。0で割るとプログラムがクラッシュするので、それを防ぐためのエラーチェックです。

アサーション

アサーションは主に開発者が設定した特定の前提条件が満たされていることを確認するために使用します。アサーションが失敗した場合、それはプログラムにバグがあるか、開発者が何か重要な事実を見落としているか、あるいは両方を示したい場合に用います。

def calculate_age(birth_year, current_year):
    assert current_year >= birth_year, "Birth year cannot be in the future"
    return current_year - birth_year

この例では、アサーションは current_yearbirth_year 以上であること、つまり生まれた年が現在の年より未来でないことを確認しています。これは明らかに開発者が前提とする状況で、もしこのアサーションが失敗すると、それはコードのどこかに問題があることを示します。

まとめると、アサーションの主な利点は「コードが正しく機能するための前提条件」を明示的に示すこと、またそれが満たされていない場合には早期にエラーを引き起こすことです。つまり、アサーションはコードの健全性を保証し、バグや想定外の状況を早期に検出するためのツールであるといえます。

関数が想定している引数の型や値の範囲、オブジェクトの状態、あるいはコードの進行にあたっての前提条件など、これらはアサーションを使って確認する―。そしてこれらが期待する通りでないとき、アサーションはエラーを発生させるため、開発者は早期に問題を察知し、バグの修正やコードの改善につなげることができるというわけです。

Python:assert文

assert 文の基本的な構文は以下の通りです。

assert expression

expression はある条件を表す式で、この評価結果は True でなければならないものです。この式が False を返す場合、Pythonは AssertionError を発生させ、プログラムの実行を停止します。

更に詳細なエラーメッセージを提供するためには、次の形式を使用することも可能です。

assert expression, "Error message"

この形式では、expressionFalse を返す場合に AssertionError を発生させるだけでなく、その際に Error message をエラーメッセージとして表示します。

以下に具体的な例を示します。

def apply_discount(product, discount):
    price = product.price * (1.0 - discount)
    assert 0 <= price <= product.price, "The discounted price cannot be negative or more than the original price."
    return price

この関数では、割引後の価格が負になったり、元の価格より高くなったりしないことを確認するために assert 文が使われています。

このチェックにより、関数が不適切な割引を適用しようとすると、プログラムは AssertionError を発生させて処理を停止します。その際 "The discounted price cannot be negative or more than the original price." というエラーメッセージを表示するようにしています。

他にも様々な例が考えられます。いくつかサンプルコードを記載しておきます。

サンプル オブジェクトが特定の属性を持つことを確認する

class MyClass:
    def __init__(self, value):
        self.value = value

def process_object(obj):
    assert isinstance(obj, MyClass), "objはMyClassのインスタンスである必要があります"
    assert hasattr(obj, "value"), "objは'value'という属性を持つ必要があります"
    # objを処理...
    return obj.value * 2

参考 クラスの使い方

このコードでは、process_object 関数が引数として MyClass のインスタンスを受け取り、そのインスタンスが value 属性を持っていることを確認しています。

サンプル 関数の引数が特定の範囲にあることを確認する

def calculate_discounted_price(price, discount):
    assert isinstance(price, (int, float)) and price > 0, "価格は正の数値である必要があります"
    assert isinstance(discount, (int, float)) and 0 <= discount <= 100, "割引は0%以上100%以下の数値である必要があります"
    return price * (1 - discount / 100)

このコードでは、calculate_discounted_price 関数が引数として正の数値である price と、0%以上100%以下である discount を受け取ることを確認しています。

Python:assert文を利用する際の注意点

最後にassert文を利用する際の注意点について整理しておきます。

assert 文を利用する際には、以下のようないくつかの注意点を把握しておきましょう。

  1. assert 文はデバッグ目的: assert 文は主に開発やデバッグのフェーズで利用され、コードが想定通りの状態であることを確認するためのものです。実運用時のエラーハンドリング(例:ユーザー入力の検証)には、通常は assert 文ではなく、適切なエラーハンドリング(例:例外処理)を行うべきです。
  2. assert 文の無効化: Pythonの実行オプション -O-OO を用いると、assert 文はすべて無視されます。つまり、これらのオプションで実行すると、assert 文によるエラーチェックは行われなくなります。そのため、アサーションは、あくまで開発中やテスト中にバグを見つけるためのものであり、プログラムの正常な動作を確保するための手段ではありません。
  3. assert 文とパフォーマンス: assert 文の後ろのコードは常に評価されます。そのため、時間のかかる処理や重い計算を assert 文に直接書くと、その処理は必ず実行され、無駄なパフォーマンスの低下を引き起こす可能性があります。例えば assert に直接大きなデータの処理を書くのではなく、その結果を変数に格納してから assert するようにしましょう。
  4. エラーメッセージを明確に: assert 文の後に、エラーメッセージを追加することができます。これはアサーションが失敗したときにどのような状況だったのかを明確にするために非常に役立ちます。したがって、可能であればエラーメッセージをつけて、アサーションが何を確認しているのか、なぜそれが重要なのかを明示しましょう。

以上が assert 文を利用する際の注意点です。これらを意識して、適切に assert 文を使用すると、コードのバグを早期に見つけるのに役立ちます。

Python:assert文のまとめ

assert文の使い方
  • assert 文は開発やデバッグ時にプログラムの状態を確認するために使用される
  • assert 文は指定した条件が True でないときに AssertionError を引き起こす
  • assert 文は主に開発者の前提条件を確認するために使用される
  • Pythonの -O-OO オプションで実行すると assert 文は無効化される
def calculate_percentage(value, total):
    # 値が0以上で、全体の値以下であることを確認
    assert 0 <= value <= total, "value must be between 0 and total"
    return (value / total) * 100

始めてPythonを勉強するのは結構難しいですよね。

でもその悩みを抱えているのは一人じゃありません。全てのPython使いが同じ道を進んできました。

Pythonをはじめとするプログラミングスキルを武器に、時間と場所に捉われない自由な生き方を目指してみませんか?今すぐ行動したい方は以下の記事をチェック!

読者料典 Python入門:学習カリキュラム ←こちらから!

このWebサイトは現役のエンジニアが以下3点を目的として運営しています。

  1. 勉強:一度理解した内容を忘れないように。
    → アウトプットは「最強のインプット」である! 
  2. 備忘:忘れたとしても後から見返せるように。
    → 未来の自分への「お手紙」を書いています。 
  3. 共有:〇〇ってこうだったんだ!の感動をシェアできるように。
    → あなたの知識は誰かにとっての「価値ある情報」です。 

副業ブログの始め方はこちらから

スポンサーリンク
Python
シェアする
ビズドットオンラインをフォローする
タイトルとURLをコピーしました