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からわかりやすくサンプルコード付きで丁寧に解説します。
Pythonエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。
Python:アサーション(assertion)とは
アサーション(assertion)とは、プログラムが特定の状態であることを確認するためのチェックのことを指します。アサーションは通常、プログラムが期待する状態や条件が満たされているかを確認するために使用されます。
わかりやすく言い換えると、コードが正しく機能するための前提条件を設定するものであり、その前提条件が満たされないとき(つまり、開発者にとって想定外の状況が生じたとき)に警告を発するものです。
具体例を考えてみましょう。
あなたが1つのWebアプリケーションを開発していて、このアプリケーションはユーザーから提供された年齢に基づいて特定の情報を提供する機能を有しているとします。しかし、通常「年齢」はマイナス値であるわけがないので、年齢は必ず0以上の数値でなければならない、という前提を置いていたとしてます。
このとき、この前提条件を保証するために利用するのがアサーションです。
def provide_information(age): assert age >= 0, "Age cannot be negative!" # 年齢に基づいて情報を提供するコード...
この関数は、年齢が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
この例では、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_year
が birth_year
以上であること、つまり生まれた年が現在の年より未来でないことを確認しています。これは明らかに開発者が前提とする状況で、もしこのアサーションが失敗すると、それはコードのどこかに問題があることを示します。
まとめると、アサーションの主な利点は「コードが正しく機能するための前提条件」を明示的に示すこと、またそれが満たされていない場合には早期にエラーを引き起こすことです。つまり、アサーションはコードの健全性を保証し、バグや想定外の状況を早期に検出するためのツールであるといえます。
関数が想定している引数の型や値の範囲、オブジェクトの状態、あるいはコードの進行にあたっての前提条件など、これらはアサーションを使って確認する―。そしてこれらが期待する通りでないとき、アサーションはエラーを発生させるため、開発者は早期に問題を察知し、バグの修正やコードの改善につなげることができるというわけです。
Python:assert文
assert
文の基本的な構文は以下の通りです。
assert expression
expression
はある条件を表す式で、この評価結果は True
でなければならないものです。この式が False
を返す場合、Pythonは AssertionError
を発生させ、プログラムの実行を停止します。
更に詳細なエラーメッセージを提供するためには、次の形式を使用することも可能です。
assert expression, "Error message"
この形式では、expression
が False
を返す場合に 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
文を利用する際には、以下のようないくつかの注意点を把握しておきましょう。
assert
文はデバッグ目的:assert
文は主に開発やデバッグのフェーズで利用され、コードが想定通りの状態であることを確認するためのものです。実運用時のエラーハンドリング(例:ユーザー入力の検証)には、通常はassert
文ではなく、適切なエラーハンドリング(例:例外処理)を行うべきです。assert
文の無効化: Pythonの実行オプション-O
や-OO
を用いると、assert
文はすべて無視されます。つまり、これらのオプションで実行すると、assert
文によるエラーチェックは行われなくなります。そのため、アサーションは、あくまで開発中やテスト中にバグを見つけるためのものであり、プログラムの正常な動作を確保するための手段ではありません。assert
文とパフォーマンス:assert
文の後ろのコードは常に評価されます。そのため、時間のかかる処理や重い計算をassert
文に直接書くと、その処理は必ず実行され、無駄なパフォーマンスの低下を引き起こす可能性があります。例えばassert
に直接大きなデータの処理を書くのではなく、その結果を変数に格納してからassert
するようにしましょう。- エラーメッセージを明確に:
assert
文の後に、エラーメッセージを追加することができます。これはアサーションが失敗したときにどのような状況だったのかを明確にするために非常に役立ちます。したがって、可能であればエラーメッセージをつけて、アサーションが何を確認しているのか、なぜそれが重要なのかを明示しましょう。
以上が assert
文を利用する際の注意点です。これらを意識して、適切に assert
文を使用すると、コードのバグを早期に見つけるのに役立ちます。
Python:assert文のまとめ
始めてPythonを勉強するのは結構難しいですよね。
でもその悩みを抱えているのは一人じゃありません。全てのPython使いが同じ道を進んできました。
Pythonをはじめとするプログラミングスキルを武器に、時間と場所に捉われない自由な生き方を目指してみませんか?今すぐ行動したい方は以下の記事をチェック!
読者料典 Python入門:学習カリキュラム ←こちらから!