简体   繁体   中英

Best way to ensure user to specify one and only one of the two function parameters in Python

In some_function , I have two parameters freq and frac , I don't want users to specify both of them, or none of them. I want them to specify just one of them.

Here is the working code:

def some_function(freq=False, frac=False):
    if (freq is False) & (frac is False):
        return (str(ValueError)+': Both freq and frac are not specified')
    elif (freq is not False) & (frac is not False):
        return (str(ValueError)+': Both freq and frac are specified')
    elif (freq is not False) & (frac is False):
        try:
            print ('Do something')
        except Exception as e:
            print (e)
    elif (freq is False) & (frac is not False):
        try: 
            print ('Do something else')
        except Exception as e:
            print (e)
    else: return (str(ValueError)+': Undetermined error')

Are there better and less verbose practices to express this in Python?

You can use assert before your if statement. The type of your inputs is unclear; in general, I would use None if I know this isn't a valid input.

def some_function(freq=None, frac=None):

    freq_flag = freq is not None
    frac_flag = frac is not None

    assert freq_flag + frac_flag == 1, "Specify exactly one of freq or frac"

    if freq_flag:
        print('Do something')

    elif frac_flag:
        print('Do something else')

There's a lot you're doing wrong here. You can test not frac instead of frac is False , you should be using logical and instead of bitwise & , and you should be raising those ValueError s, not returning them:

def some_function(freq=False, frac=False):
    if not freq and not frac:
        raise ValueError('Both freq and frac are not specified')
    elif freq and frac:
       raise ValueError('Both freq and frac are specified')
    elif freq:      
        print ('Do something')
    else:
        print ('Do something else')

Generally though, you're looking for one of two options. Why not require that the user pass a single boolean, then represents freq if True and frac if False ?

def some_function(freq):
    if freq: 
        print ('Do something')
    else:
        print ('Do something else')

Dead simple pythonic solution: use two distinct functions (they can eventually just be facades for the real one):

__all__ = ["freqfunc", "fracfunc"]

# private implementation
def _somefunc(freq=False, frac=False):
   # your code here

def freqfunc(freq):
    return _somefunc(freq=freq)

def fraqfunc(frac):
    return _somefunc(frac=frac)

Now there might be better solutions but it's impossible to tell without more details...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM