Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python- Is it wrong to use default values for required parameters in function def?

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.

like image 378
quicksilvermd Avatar asked Oct 20 '25 11:10

quicksilvermd


2 Answers

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
like image 170
Blckknght Avatar answered Oct 23 '25 01:10

Blckknght


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']
like image 29
jfs Avatar answered Oct 23 '25 00:10

jfs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!