python - 尝试函数调用的变化,直到完成而不抛出异常
问题描述
我需要按顺序进行多个函数调用,直到一个返回而不抛出异常。这些函数根据输入数据执行不同的方法来解决问题。
在长格式中,以下工作:
try:
answer = method1(data, x, y, z)
except MyException:
try:
answer = method2(data, x, y, z, factor=1.0)
except MyException:
try:
answer = method3(data, x, y, z, factor=2.0)
except MyException:
...
在伪代码中,我的目标是更干净、更容易扩展:
tryUntilOneWorks:
answer = method1(data, x, y, z)
answer = method2(data, x, y, z, factor=1.0)
answer = method2(data, x, y, z, factor=2.0)
answer = method3(a, b, c)
answer = method4(data)
except:
# No answer found
解决方案
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)
推荐阅读
- mysql - Peewee 行级阻塞
- javascript - 使用php循环时无法在jquery中获取其他文件
- c - 从 Windows 到 Linux 的端口 C 项目
- javascript - jQuery('select:focus').blur() 在 Safari 和 Edge 中不起作用
- ios - 复选框选中和未选中不保留在我的表格视图中
- php - 不返回 ip-api.com 的结果(从 IP 地址查找 ISP)
- laravel - 使用单一策略方法覆盖对资源的每个操作
- python - Django 中的 AUTH_LDAP_REQUIRE_GROUP 问题
- javascript - 将被点击元素的道具作为参数传递给函数 - React / D3
- android - 从java中的字符串中删除双引号