考虑Python中的一个案例,其中一个使用getattr
来动态获取方法或值。
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
调用,无论如何都会隐式返回 - 这对于这种函数来说不一定是很好的行为。
为了确定一个坚实的相信我,你不想回归这个"面对没有好的和体面的哨兵的价值(我知道无论如何),我考虑将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时,消息总是至少在up-up-up上,因为它在你要求它查找时找到了None。然后它也会引发你期望的异常:没有这种方法/ ivar的对象的AttributeError,传递了太多args的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)
感觉就像许多额外的代码只是为了确保以正确的方式失败。一个引发异常的函数,它只是一个引用首选异常的McGuffin,只是为了安抚eafp
半神...... Hrrm。
是否有更简单的语法来声明有效的'失败'哨兵,在这种情况下还是在其他情况下,不知道或保证返回值?
答案 0 :(得分:2)
根本不要给getattr()
默认的 ; 提出AttributeError
甚至TypeError
以获取错误的msg
值,而不是:
>>> getattr(object(), 'foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'
>>> getattr(object(), 42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
简化了您的方法:
def message(obj, msg, *args, **kwargs):
result = getattr(obj, msg)
try:
return result(*args, **kwargs)
except TypeError:
return result
或者,对于您的更新版本,如果您传入参数,则重新加注大致相同:
def message(obj, msg, *args, **kwargs):
result = getattr(obj, msg)
try:
return result(*args, **kwargs)
except TypeError:
if not args and not kwargs:
# assume attribute access was desired
return result
raise