是否有更好的方法来执行以下操作:
try:
a.method1()
except AttributeError:
try:
a.method2()
except AttributeError:
try:
a.method3()
except AttributeError:
raise
看起来很讨厌,我宁愿不这样做:
if hasattr(a, 'method1'):
a.method1()
else if hasattr(a, 'method2'):
a.method2()
else if hasattr(a, 'method3'):
a.method3()
else:
raise AttributeError
保持最高效率。
答案 0 :(得分:24)
对第二个的略微改变看起来非常漂亮和简单。我真的怀疑你会注意到两者之间的性能差异,这比嵌套的try / excepts好一点
def something(a):
for methodname in ['method1', 'method2', 'method3']:
try:
m = getattr(a, methodname)
except AttributeError:
pass
else:
return m()
raise AttributeError
另一种非常易读的方法是......
def something(a):
try:
return a.method1()
except:
pass
try:
return a.method2()
except:
pass
try:
return a.method3()
except:
pass
raise AttributeError
虽然很长,很明显函数正在做什么。性能真的不应该是一个问题(如果一些try / except语句明显减慢脚本速度,脚本结构可能存在更大的问题)< / p>
答案 1 :(得分:22)
也许你可以尝试这样的事情:
def call_attrs(obj, attrs_list, *args):
for attr in attrs_list:
if hasattr(obj, attr):
bound_method = getattr(obj, attr)
return bound_method(*args)
raise AttributeError
你会这样称呼:
call_attrs(a, ['method1', 'method2', 'method3'])
这将尝试按照它们在列表中的顺序调用方法。如果你想传递任何参数,你可以在列表之后传递它们,如下所示:
call_attrs(a, ['method1', 'method2', 'method3'], arg1, arg2)
答案 2 :(得分:5)
method = (
getattr(a, 'method1', None) or
getattr(a, 'method2', None) or
getattr(a, 'method3')
)
method()
首先会查找method1
,然后是method2
,然后是method3
。一找到其中一个,搜索就会停止。如果找不到任何方法,则最后getattr
将引发异常。
答案 3 :(得分:4)
如何在函数中封装调用?
def method_1_2_or_3():
try:
a.method1()
return
except AttributeError:
pass
try:
a.method2()
return
except AttributeError:
pass
try:
a.method3()
except AttributeError:
raise
答案 4 :(得分:3)
紧凑的解决方案:
getattr(a, 'method1',
getattr(a, 'method2',
getattr(a, 'method3')))()
答案 5 :(得分:1)
如果您使用的是新式对象:
methods = ('method1','method2','method3')
for method in methods:
try:
b = a.__getattribute__(method)
except AttributeError:
continue
else:
b()
break
else:
# re-raise the AttributeError if nothing has worked
raise AttributeError
当然,如果您没有使用新式对象,可以尝试使用__dict__
代替__getattribute__
。
编辑:这段代码可能被证明是一个尖叫的混乱。如果找不到__getattribute__
或__dict__
,请大胆猜测会出现什么样的错误。