如果您需要多次执行此操作,您可以将 Hyperboreus 和其他人给出的答案打包为一个函数:
def first_success(*callables):
for f in callables:
try:
return f()
except Exception as x:
print('{} failed due to {}'.format(f.__name__, x))
raise RuntimeError("still fail")
然后,您只需要:
first_success(trial_1, trial_2, trial_3, trial_4)
如果您想要logging.info
异常而不是print
它们,或者完全忽略它们,或者跟踪它们并将异常列表附加到返回值和/或异常作为属性等,那么如何修改它应该很明显.
如果您想将参数传递给函数,那不是很明显,但仍然很容易。你只需要决定接口应该是什么。也许将一系列可调用对象作为第一个参数,然后是所有可调用对象的参数:
first_success((trial_1, trial_2, trial_3, trial_4), 42, spam='spam')
这很容易:
def first_success(callables, *args, **kwargs):
for f in callables:
try:
return f(*args, **kwargs)
except Exception as x:
print('{} failed due to {}'.format(f.__name__, x))
else:
raise RuntimeError("still fail")
如果你并不总是需要这种模式,但你需要大量不完全一样的东西,你可能想要编写一个函数,将任何函数包装在try
. 我实际上已经构建了六次,然后意识到有一种更pythonic的方式来编写我的代码,这使得这个函数变得不必要,所以我唯一得到的用途是在与 Haskell snobs 的参数中,但是您可能会找到更好的用途:
def tried(callable, *args, **kwargs):
try:
return (callable(*args, **kwargs), None)
except Exception as x:
return (None, x)
现在你可以使用高阶map
函数any
如Haskell 程序员讨厌你。map(tried, (trial_1, trial_2, trial_3, trial_4))
(f(x[0]) if x[1] is None else x for x in tried_sequence)