I have a func which looks like this:
def somefunc(param1, param2, param3=None, param4=None, param5=None):
if not all([param3, param4, param5]):
raise ValueError("Invalid Parameters")
#continue with rest of the logic if no "ValueError"
param3, param4, param5 are all required by the func. I have a restriction of max 3 positionals based on how the func is called. I can either gather them as individual keyword parameters with default values of None like I have shown above OR as **kwargs which can accept a dictionary of params.
Since I am checking if each param has some value assigned or else raise a ValueError, is it wrong to use such default values for required params during func def.
I understand the problem with mutable default values as explained here Default Parameter Values in Python. But is using a sentinel object or something like None for required func args still a bad practice?
Also if this is not a good practice what would be a right way to do this? Thanks.
In Python 3, you can have required variables that must be passed by keyword:
def somefunc(pos1, pos2, *, kwonly3, kwonly4): # kwonly3 and kwonly4 are still required!
pass
But I'm not sure that you necessarily need this. If your function would make sense with the parameters all being positional, you can still call it via an API that passes them by keyword:
def somefunc2(pos1, pos2, pos3, pos4): # all parameters are required
pass
# you can call the function with keyword arguments, or even with **kwargs
somefunc2("foo", "bar", pos3="baz", **{"pos4": "quux"}) # this will work
Passing wrong number of arguments to a function is TypeError in Python. Passing a wrong value such as None in your case may be ValueError.
To emulate somefunc(param1, param2, *, param3, param4, param5) in Python 2:
def somefunc(param1, param2, **kwargs):
if somefunc.kwargs != sorted(kwargs):
raise TypeError('Expected exactly %d keyword-only args: %r; got %r' % (
len(somefunc.kwargs), somefunc.kwargs, kwargs))
if any(v is None for v in kwargs.values()):
raise ValueError("%s can't be None; got %r" % (
", ".join(somefunc.kwargs), kwargs))
somefunc.kwargs = ['param3', 'param4', 'param5']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With