getattr
メソッドまたは値を動的に取得するために使用する Python のケースを考えてみましょう。
def message(obj, msg, *args, **kwargs):
result = getattr(obj, msg, None)
if result is not None:
try:
return result(*args, **kwargs)
except TypeError:
return result
...ただ、ちょっと待ってください。それはあまり良い振る舞いではありません。これが不適切なgetattr
呼び出しであったとしても、暗黙的に None が返されます。これは、この種の関数にとって必ずしも優れた動作ではありません。
(とにかく私が知っていた) 善良でまともな歩哨に直面して、確かな「私を信じてください、あなたはこれを返したくない」値を決定するために、私getattr
は例外。このように、「他の男」がかわいいと決めて、この役に立たない歩哨を属性にしない限り、悪い検索は常に明白で捕らえられるべきです.
class _BadMessageException(Exception):
pass
def _did_not_find(*args, **kwargs):
raise BadMessageException
def _raise_right_exception(msg, obj):
if not isinstance(msg, basestring):
raise TypeError("Message '{}' was not a string".format(msg))
else:
raise AttributeError("Bad message '{}' sent to object '{}'".format(msg, obj))
このように、None を返すとき、メッセージは常に少なくとも上向きになります。また、予想される例外も発生します。そのようなメソッド/ ivar がないオブジェクトの場合は AttributeError、渡された引数が多すぎる場合は TypeError などです。編集:当然、最初に間違ったコード スニペットを投稿します。これが修正された関数です。
def message(obj, msg, *args, **kwargs):
result = getattr(obj, msg, _did_not_find)
try:
return result(*args, **kwargs)
except TypeError:
if not args or kwargs:
return result
else:
_raise_right_exception(msg, obj)
except _BadMessageException:
_raise_right_exception(msg, obj)
これが正しい方法で失敗することを確認するためだけに、余分なコードがたくさんあるように感じます。半神をなだめるためだけに、優先eafp
例外を発生させるためのMcGuffinである例外を発生させる関数...うーん。
戻り値が不明または保証されていないこの状況または他の状況で、有効な「失敗」センチネルを宣言するためのより簡単な構文はありますか?