I am implementing a function with three keywords. The default value for each keyword is None, but I need to force the user to pass at least one keyword. The reason why I want to use keywords is that the keyword names a, b and c are descriptive, and will help the user to figure out what does he need to pass to method. How do I achieve my task?

def method(a=None, b=None, c=None):

    if a!=None:
        func_a(a)
    elif b!=None:
        func_b(b)
    elif c!=None:
        func_c(c)
    else:
        raise MyError('Don\'t be silly, user - please!')

In the above example, assume of course that a, b and c have different attributes. The obvious solution would be:

def method(x):
    if is_instance(x, A):
        func_a(x)
    elif is_instance(x, B):
        func_b(x)
    [...]

But the problem is that as I said I want to use the keyword names a, b and c to help the user understand what he does need to pass to method!

Is there a more pythonic way to achieve the result?

有帮助吗?

解决方案 4

Try this expression to evaluate that at least one argument is passed

if not (a or b or c):
    raise MyError

其他提示

You could use all() to raise an error early:

def foo(a=None, b=None, c=None):
    if all(x is None for x in (a, b, c)):
        raise ValueError('You need to set at least *one* of a, b, or c')

    if a is not None:
        func_a(a)
    # etc.

You can use decorator, simulating the Contract programming paradigm.

def check_params(func):
    def wrapper(*args, **kwargs):
        a = kwargs.get('a', None)
        b = kwargs.get('b', None)
        c = kwargs.get('c', None)
        if (a == b == c == None):
            raise Exception("Set one of a, b or c is mandatory.")
        else:
            return func(*args, **kwargs)
    return wrapper


@check_params
def foo(a=None, b=None, c=None):
    print("Ok")


foo(a=4)  # This will print ok.
foo()     # This will rise an exception.

Note that a call such as method(b="something", a="otherthing") would return func_a(a), and not func_b(b), which the user might expect. In fact, it would be better to make sure one and only one keyword is not None (see e.g. here), for which it would probably make more sense for the user to simply directly call the respective methods (though you might want to call them method_from_a etc. then).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top