「最新のPythonでカスタム例外を宣言する適切な方法は?」
あなたの例外が本当により具体的な例外のタイプでない限り、これは問題ありません:
class MyException(Exception):
pass
pass
docstring を与える代わりに、より良い(多分完璧かもしれません):
class MyException(Exception):
"""Raise for my specific kind of exception"""
例外サブクラスのサブクラス化
ドキュメントから
Exception
システムに存在しない組み込みの例外はすべて、このクラスから派生します。すべてのユーザー定義の例外もこのクラスから派生する必要があります。
つまり、例外がより具体的な例外のタイプである場合、ジェネリックの代わりにその例外をサブクラス化しますException
(その結果Exception
、ドキュメントが推奨するとおりに引き続き派生します)。また、少なくともdocstringを提供できます(pass
キーワードを強制的に使用する必要はありません)。
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
カスタムで自分で作成した属性を設定します__init__
。dictを位置引数として渡さないでください。将来のコードのユーザーはあなたに感謝します。非推奨のメッセージ属性を使用する場合、自分で割り当てると、次のような事態を回避できますDeprecationWarning
。
class MyAppValueError(ValueError):
'''Raise when a specific subset of values in context of app is wrong'''
def __init__(self, message, foo, *args):
self.message = message # without this you may get DeprecationWarning
# Special attribute you desire with your Error,
# perhaps the value that caused the error?:
self.foo = foo
# allow users initialize misc. arguments as any other builtin Error
super(MyAppValueError, self).__init__(message, foo, *args)
自分で__str__
or を書く必要は本当にありません__repr__
。ビルトインのものはとても素晴らしいです、そしてあなたの協調的な継承はあなたがそれを使うことを保証します。
トップアンサーの批評
多分私は質問を逃しました、しかしなぜそうしないのですか:
class MyException(Exception):
pass
繰り返しますが、上記の問題は、それをキャッチするために、具体的に名前を付ける(他の場所で作成された場合はインポートする)か、例外をキャッチする必要があることです(ただし、すべてのタイプの例外を処理する準備が整っていない可能性があります)。処理する準備ができている例外のみをキャッチする必要があります)。以下と同様の批判super
ですが、それはを介して初期化する方法ではありません。DeprecationWarning
メッセージ属性にアクセスすると、
編集:何かをオーバーライドする(または追加の引数を渡す)には、次のようにします。
class ValidationError(Exception):
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(ValidationError, self).__init__(message)
# Now for your custom code...
self.errors = errors
そうすれば、エラーメッセージの辞書を2番目のパラメーターに渡し、後でe.errorsでそれを取得できます
(self
。を除いて)正確に2つの引数を渡す必要もあります。これは、将来のユーザーが理解できないかもしれない興味深い制約です。
直接的であること- リスコフの代替可能性に違反します。
両方のエラーを説明します。
>>> ValidationError('foo', 'bar', 'baz').message
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)
>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'
に比べ:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'