Skip to content Skip to sidebar Skip to footer

Trying Variations On A Function Call Until One Completes Without Throwing Exception

Related to Trying different functions until one does not throw an exception I need to make multiple function calls, in sequence, until one returns without throwing an exception. Th

Solution 1:

What Aran-Fey is suggesting is probably the simplest solution: create a list of function objects on the fly that call the methods that you want in the way that you want:

deffind_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:
            passraise MyException('All methods failed')

This requires a good amount of hard-coding, so I would recommend something a bit more general. You could pass in all the possible arguments, keyword or otherwise, along with a spec for how to apply them to each function:

deffind_one_that_works(methods, specs, *args, **kwargs):
    defget(k):
        return kwargs[k] ifisinstance(k, str) else args[k]

    for method, (arg_spec, kwarg_spec) inzip(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:
            passraise MyException('None succeeded')

This allows you to specify a tuple of selections for the positional arguments and a mapping of selections for keyword arguments that will be extracted from everything you pass into the function. The example in your question would be called like this:

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)

The nice thing is that you can name all your arguments this way too. The following is identical to the above:

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)

Post a Comment for "Trying Variations On A Function Call Until One Completes Without Throwing Exception"