I have a function with two optional arguments that I'd like to require either both, or neither to be specified. What is the preferred way of enforcing this in Python? My current approach seems a bit awkward:
def myfunc(data, opt1=None, opt2=None):
if opt1 is None or opt2 is None:
if not (opt1 is None and opt2 is None):
raise ValueError("Must specify both opt1 and opt2 or neither.")
This question: Python Optional Argument Pair is the same as mine, but in the context of argparse
specifically; I am interested in the default way of doing this within functions generally.
The simplified condition you're looking for is:
if (opt1 is None) != (opt2 is None):
raise ...
This condition is true if both arguments don't fall on the same side of is None
together.
You could define a function
def ensure_both_or_neither(opt1, opt2):
if opt1 is None or opt2 is None:
if not (opt1 is None and opt2 is None):
raise ValueError("Must specify both opt1 and opt2 or neither.")
Then call it from your function:
def myfunc(data, opt1=None, opt2=None):
ensure_both_or_neither(opt1, opt2)
I don't think it's any better than your orignal approach, but it is slightly more explicit / readable?
def myfunc(data, *args):
if(len(args)==0 or len(args)==2):
#do something
Is how I would do it
This also enables you to have as many arguments as you want, and only if none or 2 are used the code is run
You can use the fact that a set
removes duplicates:
def myfunc(data, opt1=None, opt2=None):
if len({opt1 is None, opt2 is None}) - 1:
raise ValueError("Must specify both opt1 and opt2 or neither.")
You could do it for any number of parameters:
def myfunc(data, *args):
if len({arg is None for arg in args}) - 1:
raise ValueError("Must specify all parameters or none.")
If you need neither or both, don't accept two separate arguments; accept a single optional tuple and document it. Don't give the user the opportunity to only provide one.
def myfunc(data, opts=None):
"""blah blah blah
opts, if given, should be a tuple with two values, neither None.
"""
opt1, opt2 = opts if opts is not None else (None, None)
You could make the default (None, None)
, which would simplify the unpacking inside your function ( x1, x2 = opts
), but at the expense of cluttering your function's signature.
(In reality, opts
can be an iterable with 2 elements, but if the user makes a call like myfunc(data, "hi")
and expects opt1
to be hi
and opt2
to be None
, that's his fault, not yours.)
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.