新しい本「PythonProSecrets」へのあなたの興味は、 Pythonの癖の物語が続くに値することを私たちに確信させました。今日は、カスタム(テキスト内-独自の)例外クラスの作成に関する小さなチュートリアルを読むことを提案します。著者はそれを面白くしました、例外の最も重要な利点がエラーメッセージの完全性と明快さであるということを彼に反対するのは難しいです。オリジナルのコードの一部は写真の形をしています。
猫へようこそ。
独自のエラークラスの作成
Pythonには、独自の例外クラスを作成する機能があります。このようなクラスを作成することにより、アプリケーション内のクラスの設計を多様化できます。エラーのカスタムクラスは、エラーをログに記録し、オブジェクトを検査する可能性があります。例外クラスが何をするかを定義するのは私たちですが、通常、カスタムクラスはメッセージを表示する以上のことはほとんどできません。
当然、エラータイプ自体は重要であり、通常はPython言語レベルではカバーされない特定の状況を示すために、独自のエラータイプを作成することがよくあります。このようにして、クラスのユーザーは、このエラーが発生したときに何が起こっているかを正確に知ることができます。
この記事は2部に分かれています。まず、例外クラスを単独で定義します。次に、独自の例外クラスをPythonプログラムに統合する方法を示し、設計したクラスの使いやすさを向上させる方法を示します。
MyCustomErrorカスタム例外クラス
例外をスローするには、
__init__()
andメソッドが必要
__str__()
です。
例外をスローするとき、すでに例外のインスタンスを作成し、同時にそれを画面に表示します。以下に示すカスタム例外クラスを詳しく見てみましょう。
上記MyCustomErrorクラスは2つのマジックメソッド、あり
__init__
と
__str__
自動的に例外処理中に呼び出され、。メソッド
Init
はインスタンスの作成時に呼び出され、メソッド
str
はインスタンスの表示時に呼び出さ れます。したがって、例外がスローされると、通常、これら2つのメソッドは互いに直後に呼び出されます。 Pythonの例外throwステートメントは、プログラムをエラー状態にします。
メソッドの引数リスト内
__init__
です
*args
。コンポーネント
*args
は、関数とメソッドで使用される特別なパターンマッチングモードです。複数の引数を渡すことができ、渡された引数をタプルとして格納できますが、同時に、引数をまったく渡さないようにすることもできます。
この場合、コンストラクターに
MyCustomError
引数が渡された場合 、最初に渡された引数を取得
message
して、オブジェクトの属性に割り当て ます。引数が渡されなかった場合、属性に
message
は値が割り当てられます
None
。
最初の例では、例外
MyCustomError
は引数なしでスローさ れるため、属性
message
このオブジェクトには値が割り当てられます
None
。メソッドが呼び出され
str
、「MyCustomErrorメッセージが発生しました」というメッセージが表示されます。
例外
MyCustomError
は引数なしでスローされます(括弧は空です)。言い換えれば、そのようなオブジェクトのデザインは非標準に見えます。ただし、これは、例外をスローするときにPythonで提供される構文サポートにすぎません。
2番目の例で
MyCustomError
は、文字列引数「問題があります」で渡されます。
message
オブジェクトの属性として設定され 、例外がスローされるとエラーメッセージとして表示されます。
MyCustomError例外クラスのコードは こちらです..。
class MyCustomError(Exception):
def __init__(self, *args):
if args:
self.message = args[0]
else:
self.message = None
def __str__(self):
print('calling str')
if self.message:
return 'MyCustomError, {0} '.format(self.message)
else:
return 'MyCustomError has been raised'
# MyCustomError
raise MyCustomError('We have a problem')
CustomIntFloatDicクラス
独自の辞書を作成します。その値は整数と浮動小数点数のみです。
先に進んで、エラークラスを独自のプログラムに簡単かつ便利に挿入する方法を示しましょう。まず、少し工夫を凝らした例を紹介します。この架空の例では、整数または浮動小数点数のみを受け入れることができる独自の辞書を作成します。
ユーザーがこの辞書の値として他のデータタイプを指定しようとすると、例外がスローされます。この例外は、この辞書の使用方法に関する有用な情報をユーザーに提供します。私たちの場合、このメッセージは、整数または浮動小数点数のみがこの辞書の値として指定できることをユーザーに直接通知します。
独自の辞書を作成するときは、辞書に値を追加できる場所が2つあることに注意してください。まず、これはオブジェクトを作成するときのinitメソッドで発生する可能性があり(この段階では、オブジェクトにはすでにキーと値を割り当てることができます)、次に、キーと値を辞書に直接設定するときに発生する可能性があります。これらの場所の両方で、値がタイプ
int
または
float
。のみであることを保証するコードを記述する必要があります 。
まず、組み込みクラスから継承するCustomIntFloatDictクラスを定義します
dict
。
dict
は、括弧で囲まれ、クラス名の後に続く引数のリストで渡され
CustomIntFloatDict
ます。
クラスがインスタンス化されている場合
CustomIntFloatDict
さらに、キーと値のパラメータに引数は渡されず、に設定され
None
ます。式は
if
次のように解釈されます。キーが等しい
None
か、値が等しい場合
None
、オブジェクトを使用してメソッドが呼び出され
get_dict()
、属性が返されます
empty_dict
。オブジェクトのそのような属性は、空のリストを指します。クラス属性は、クラスのすべてのインスタンスで使用できることに注意してください。
このクラスの目的は、ユーザーがキーと値を含むリストまたはタプルを渡すことができるようにすることです。ユーザーがキーと値を探しているリストまたはタプルを入力すると、これら2つの列挙されたセットは関数を使用して連結されます
zip
Python言語。オブジェクトを指すフックされた変数
zip
は反復可能であり、タプルはアンパック可能です。タプルを反復処理することにより、valがクラス
int
またはの インスタンスであるかどうかを確認します
float
。
val
これらのクラスのいずれにも属していない場合 は
IntFloatValueError
、独自の例外をスローし 、valを引数として渡します。
IntFloatValueError例外クラス
例外がスローされる
IntFloatValueError
と、クラスのインスタンスが作成さ れ、
IntFloatValueError
同時に画面に表示されます。これは、魔法のメソッド
init
と が呼び出されることを意味し
str
ます。
スローされた例外の原因となった値は
value
、クラスに付随 する属性として設定されます
IntFloatValueError
。 magic strメソッドを呼び出すと、ユーザーはの値が無効
init
である ことを通知するエラーメッセージを受け取り
CustomIntFloatDict
ます。ユーザーは、このエラーを修正するために何をすべきかを知っています。
例外クラス
IntFloatValueError
および
KeyValueConstructError
例外がスローされない場合、つまりすべて
val
チェーンされたオブジェクトのタイプ
int
または
float
、の場合、それらはを使用して設定 され、以下に示すように
__setitem__()
、親クラスのメソッドがすべてを実行し
dict
ます。
KeyValueConstructErrorクラス
ユーザーがリストまたはキーと値のタプルではないタイプを入力するとどうなりますか?
繰り返しますが、この例は少し人工的なものですが、独自の例外クラスを使用する方法を示すと便利です。
ユーザーがキーと値をリストまたはタプルとして指定しない場合、例外がスローされ
KeyValueConstructError
ます。この例外の目的は、キーと値をオブジェクトに書き込むために
CustomIntFloatDict
、リストまたはタプルを
init
クラス コンストラクターで指定する必要があることを ユーザーに通知することです
CustomIntFloatDict
。
上記の例では、コンストラクターの2番目の引数として
init
多くが渡され、このために例外がスローされました
KeyValueConstructError
。表示されるエラーメッセージの利点は、表示されるエラーメッセージが、挿入されるキーと値をリストまたはタプルとして報告する必要があることをユーザーに通知することです。
この場合も、例外がスローされると、KeyValueConstructErrorインスタンスが作成され、キーと値が引数としてKeyValueConstructErrorコンストラクターに渡されます。これらは、KeyValueConstructErrorのキーおよび値属性の値として設定され、メッセージが画面に表示されたときに意味のあるエラーメッセージを生成するために__str__メソッドで使用されます。
さらに、コンストラクターに追加されたオブジェクトに固有のデータタイプも含めます
init
-わかりやすくするためにこれを行います。
CustomIntFloatDictでキーと値を設定する
CustomIntFloatDict
から継承し
dict
ます。これは、動作を選択的に変更することを選択した場所を除いて、辞書とまったく同じように機能することを意味します。
__setitem__
辞書にキーと値を設定するときに呼び出される魔法のメソッドです。私たちの実装で
setitem
は、値がタイプ
int
またはであるか どうかをチェックし、
float
チェックが成功した後にのみ、辞書に設定できます。チェックに失敗した場合は、例外クラスを再度使用できます
IntFloatValueError
。ここ
‘bad_value’
で、辞書の値として 文字列を設定しようとする
test_4
と、例外が発生することを確認でき ます。
このチュートリアルのすべてのコードを以下に示し 、Githubに投稿します。
# , int float
class IntFloatValueError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return '{} is invalid input, CustomIntFloatDict can only accept ' \
'integers and floats as its values'.format(self.value)
class KeyValueContructError(Exception):
def __init__(self, key, value):
self.key = key
self.value = value
def __str__(self):
return 'keys and values need to be passed as either list or tuple' + '\n' + \
' {} is of type: '.format(self.key) + str(type(self.key)) + '\n' + \
' {} is of type: '.format(self.value) + str(type(self.value))
class CustomIntFloatDict(dict):
empty_dict = {}
def __init__(self, key=None, value=None):
if key is None or value is None:
self.get_dict()
elif not isinstance(key, (tuple, list,)) or not isinstance(value, (tuple, list)):
raise KeyValueContructError(key, value)
else:
zipped = zip(key, value)
for k, val in zipped:
if not isinstance(val, (int, float)):
raise IntFloatValueError(val)
dict.__setitem__(self, k, val)
def get_dict(self):
return self.empty_dict
def __setitem__(self, key, value):
if not isinstance(value, (int, float)):
raise IntFloatValueError(value)
return dict.__setitem__(self, key, value)
#
# test_1 = CustomIntFloatDict()
# print(test_1)
# test_2 = CustomIntFloatDict({'a', 'b'}, [1, 2])
# print(test_2)
# test_3 = CustomIntFloatDict(('x', 'y', 'z'), (10, 'twenty', 30))
# print(test_3)
# test_4 = CustomIntFloatDict(('x', 'y', 'z'), (10, 20, 30))
# print(test_4)
# test_4['r'] = 1.3
# print(test_4)
# test_4['key'] = 'bad_value'
結論
独自の例外を作成すると、クラスでの作業がはるかに便利になります。例外クラスにはマジックメソッドが必要で
init
あり
str
、例外処理中に自動的に呼び出されます。あなた自身の例外クラスが何をするかは完全にあなた次第です。示されているメソッドの中には、オブジェクトを検査し、画面に有益なエラーメッセージを表示するためのメソッドがあります。
とはいえ、例外クラスを使用すると、発生したエラーの処理がはるかに簡単になります。