内で例外を発生させることは悪い形と考えられます__init__
か?もしそうなら、特定のクラス変数がNone
正しくない型として初期化されたときにエラーをスローするための受け入れられた方法は何ですか?
内で例外を発生させることは悪い形と考えられます__init__
か?もしそうなら、特定のクラス変数がNone
正しくない型として初期化されたときにエラーをスローするための受け入れられた方法は何ですか?
回答:
内部__init__()
で例外を発生させることは絶対に問題ありません。コンストラクター内でエラー状態を示すための良い方法は他にありません。標準ライブラリには、オブジェクトを構築すると例外が発生する可能性のある何百もの例があります。
もちろん、発生させるエラークラスはあなた次第です。ValueError
コンストラクターに無効なパラメーターが渡された場合に最適です。
ValueError
およびTypeError
です。
__init__
はコンストラクタではなく、その初期化子であることを指摘するだけです。あなたは行を編集したい場合がありますコンストラクタ内でエラー状態を示すために、他の良い道が..ありません
コンストラクタでエラーを示す唯一の適切な方法は、例外を発生させることです。そのため、C ++や、例外の安全性を考慮して設計された他のオブジェクト指向言語では、オブジェクトのコンストラクターで例外がスローされても、デストラクタは呼び出されません(つまり、オブジェクトの初期化が不完全です)。これは、Pythonなどのスクリプト言語には当てはまりません。たとえば、次のコードは、socket.connect()が失敗した場合にAttributeErrorをスローします。
class NetworkInterface:
def __init__(self, address)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect(address)
self.stream = self.socket.makefile()
def __del__(self)
self.stream.close()
self.socket.close()
その理由は、接続の試行が失敗した後、ストリーム属性が初期化される前に、不完全なオブジェクトのデストラクタが呼び出されるためです。コンストラクターから例外をスローすることを避けてはいけません。Pythonで完全に例外セーフなコードを書くのは難しいと言っているだけです。一部のPython開発者はデストラクタの使用を完全に避けていますが、それは別の議論の問題です。
__del__
はひどく書かれているので失敗します。this->p_socket->close()
C ++でデストラクタを使用した場合も、まったく同じ問題が発生します。C ++では、そうはしません。メンバーオブジェクトにそれ自体を破壊させます。Pythonでも同じようにします。
上記のすべてに同意します。
例外を発生させる以外に、オブジェクトの初期化で何か問題が発生したことを知らせる他の方法はありません。
クラスの状態がそのクラスへの入力に完全に依存しているほとんどのプログラムクラスでは、ある種のValueErrorまたはTypeErrorが発生することが予想されます。
副作用のあるクラス(ネットワークやグラフィックを実行するクラスなど)は、(たとえば)ネットワークデバイスが利用できない場合やキャンバスオブジェクトに書き込めない場合に、initでエラーを発生させる可能性があります。障害の状態をできるだけ早く知りたいことがよくあるので、これは私には理にかなっているように思えます。