How to check in python that at least one of the default parameters of the function specified

北城以北 提交于 2021-02-04 14:58:08

问题


What is the best practice in python to check if at least one of the default parameters of the function is specified?

Let's suppose we have some function:

def some_function(arg_a=None, arg_b=None, arg_c=False)

with some default parameters. In my case, I need to check if either arg_a or arg_b is specified. So I thought of implementing something like this:

def some_function(arg_a=None, arg_b=None, arg_c=False):
    ...
    if arg_a is not None:
        ...
    elif arg_b is not None:
        ...
    else:
        raise ValueError('Expected either arg_a or arg_b args')
    ...
    ...

So, what is more pythonic way to implement such kind of functionality?


回答1:


You could use all to check if they all equal None and raise the ValueError:

if all(v is None for v in {arg_a, arg_b}):
    raise ValueError('Expected either arg_a or arg_b args')

this gets rid of those if-elif clauses and groups all checks in the same place:

f(arg_a=0) # ok    
f(arg_b=0) # ok
f()        # Value Error  

Alternatively, with any():

if not any(v is not None for v in {arg_a, arg_b}):
    raise ValueError('Expected either arg_a or arg_b args')

but this is definitely more obfuscated.

In the end, it really depends on what the interpretation of pythonic actually is.




回答2:


Depends on what you expect as values for arg_a and arg_b, but this is generally sufficient.

if not arg_a and not arg_b:
    raise ValueError(...)

Assumes that arg_a and arg_b are not both booleans and cannot have zeros, empty strings/lists/tuples, etc. as parameters.

Depending on your needs, you can be more precise if you need to distinguish between None and 'falsies' such as False, 0, "", [], {}, (), etc.:

if arg_a is None and arg_b is None:
    raise ValueError(...)



回答3:


You may consider using kwargs if you have quite a number of such named arguments with mismatching default values:

def some_function(**kwargs):
    reqd = ['arg_a', 'arg_b']
    if not all(i in kwargs for i in reqd):
        raise ValueError('Expected either {} args'.format(' or '.join(reqd)))

    arg_a = kwargs.get('args_a')
    arg_b = kwargs.get('args_b')
    arg_c = kwargs.get('args_c', False)



回答4:


To check if at least one of the default parameters of the function specified

The solution using locals, dict.values and any functions:

def some_function(arg_a=None, arg_b=None, arg_c=False):
    args = locals()
    if (any(args.values()) == True):
        print('Ok')
    else:
        raise ValueError('At least one default param should be passed!')

some_function(False, 1)            # Ok
some_function('text', False, None) # Ok
some_function(0, False, None)      # Error

https://docs.python.org/2/library/functions.html#any




回答5:


Since you're proposing such a pattern, there's possibly some unifying meaning to arg_a, arg_b and arg_c. If that's so, you could ...

from enum import Enum

class Group(Enum):
    A = auto()
    B = auto()
    C = auto()

def some_function(val: int, t: Group):
    if t == Group.A:
        # do stuff with val
    elif t == Group.B:
        # do other stuff with val
    elif t == Group.C:
        # do other stuff with val

some_function(1, Group.A)

Here the caller is forced to specify both a value, and what the value corresponds to. This is tbh a bit of a hack around the lack of proper enumeration support in python and I've no idea if it's pythonic. It will however be picked up by a type checker.



来源:https://stackoverflow.com/questions/38881888/how-to-check-in-python-that-at-least-one-of-the-default-parameters-of-the-functi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!