Aran-Fey 的建议可能是最简单的解决方案:动态创建函数对象列表,以您想要的方式调用您想要的方法:
def find_one_that_works(data, a, b, c, x, y, z, factor1, factor2):
methods = [
lambda: method1(data, x, y, z),
lambda: method2(data, x, y, z, factor=1.0),
lambda: method2(data,x,y,z,factor=2.0),
lambda: method3(a, b, c),
lambda: method4(data),
]
for method in methods:
try:
return method()
except MyException:
pass
raise MyException('All methods failed')
这需要大量的硬编码,所以我会推荐一些更通用的东西。您可以传入所有可能的参数、关键字或其他参数,以及如何将它们应用于每个函数的规范:
def find_one_that_works(methods, specs, *args, **kwargs):
def get(k):
return kwargs[k] if isinstance(k, str) else args[k]
for method, (arg_spec, kwarg_spec) in zip(methods, specs):
ar = [get(k) for k in arg_spec]
kw = {k: get(v) for k, v in kwarg_spec.items()}
try:
return method(*ar, **kw)
except MyException:
pass
raise MyException('None succeeded')
这允许您指定位置参数的选择元组和关键字参数的选择映射,这些参数将从您传递给函数的所有内容中提取。您问题中的示例将被称为:
methods = [method1, method2, method2, method3, method4]
specs = [
((0, 4, 5, 6), {}),
((0, 4, 5, 6), {'factor': 7}),
((0, 4, 5, 6), {'factor': 8}),
((1, 2, 3), {}),
((0,), {})
]
find_one_that_works(methods, specs, data, a, b, c, x, y, z, 1.0, 2.0)
好消息是你也可以用这种方式命名所有参数。以下与上述相同:
methods = [method1, method2, method2, method3, method4]
specs = [
(('data', 'x', 'y', 'z'), {}),
(('data', 'x', 'y', 'z'), {'factor': 'factor1'}),
(('data', 'x', 'y', 'z'), {'factor': 'factor2'}),
(('a', 'b', 'c'), {}),
(('data',), {})
]
find_one_that_works(methods, specs,
data=data, a=a, b=b, c=c,
x=x, y=y, z=z, factor1=1.0, factor2=2.0)