1

I would like to know what the best practice is regarding default values for functions.

Let's say I have a function:

def my_function(x, **kwargs):
    kwargs_default = {'boolean_offset': False}
    kwargs_default.update(kwargs)

    if kwargs_default['boolean_offset']:
        x += 100
    return x

It is just a quick example and does not have any other meaning.

my_function(2) will return 2. my_function(2, boolean_offset=True) will return 102.

The point is that I have a variable called boolean_offset that is turned off by default, but may be turned on by the user.

In my real problem I have a function with many input variables. Often not all of these input variables are used and in most cases users want to use the default settings. To make the code more readable I would like to use *args and **kwargs. Further I would like the potentially used variables to have default values, which can be overwritten by the user.

Is the code in my example the best way to do this?

Marnix
  • 719
  • 1
  • 6
  • 14
  • 2
    How is it making the code more readable to use `**kwargs`, if you have to specify the default values one line below anyways? – L3viathan Mar 26 '18 at 11:02
  • 1
    _"To make the code more readable I would like to use *args and **kwargs."_ Does not compute. How do those make code _more_ readable? What's wrong with using parameters with default values like `def my_function(x, boolean=False)`? – Aran-Fey Mar 26 '18 at 11:02
  • 1
    Just use `def my_function(x, boolean_offset=True)` instead of `**kwargs`. I rarely (never?) use the latter outside of wrapper-functions and decorators. – tobias_k Mar 26 '18 at 11:06
  • Best practice in your case would be to have default parameters and stay away from `*args` and `**kwargs`. This answer explains well when and why to use or not use `*args` and `**kwargs`: https://stackoverflow.com/questions/1415812/why-use-kwargs-in-python-what-are-some-real-world-advantages-over-using-named – Karl Anka Mar 26 '18 at 11:11
  • @KarlAnka I think the anaswer in the linked thread are not good - for instance, using **kwargs to pass parameters to an inner function is a pattern best reserved for situation where you don't KNOW which parameters will be used by the inner function. For the common case "wrap a method, then call it" it's better to repeat the parameters, otherwise the user of the function has to figure out which parameterrs are ok. The effect can be seens in libs like matplotlib, where function interface are worthless "take everything" facades – Christian Sauer Mar 26 '18 at 14:15

3 Answers3

4

*args and **kwargs do not make the code more readable, on the contrary, they are pure hell. Before, your editor could show you the function parameters, now there is just **kwargs - and there is no reliable way to find which parameters can or must be set.

If you have many parameters, you should either split the function or add a configuration class , which can be leveraged to make sanity checks, too.

Christian Sauer
  • 10,351
  • 10
  • 53
  • 85
1

You can use **kwargs or *args. If you want to use **Kwargs, i would add the default value of boolean_offset in the declaration, like this:

def my_function(x, boolean_offset = False, **kwargs)

and i would use **kwargs for pass more arguments without default value.

Baurin Leza
  • 2,004
  • 1
  • 13
  • 15
0

While I do agree with the fact that using *args / **kwargs is not the way to go, if you still wish to do something around these lines you could define a default dict and work with it.

something like this :

from collections import defaultdict
def my_function(x, **kwargs):
    my_default_dict = defaultdict(lambda : False)
    for key in kwargs.keys():
        my_default_dict[key] = kwargs[key]

This is assuming you want all your default values to be a certain value(false in this case) - You can then work with my_default_dict. In any other case you will have to do it manually (Further strengthening the answer above me).

Rohi
  • 814
  • 1
  • 9
  • 26
  • What if the default for another parameter is `True`, or `42`? You could, however, use `kwargs.get("boolean_offset", False)` in the condition. – tobias_k Mar 26 '18 at 11:54
  • Yep, thats why I agree with what was said above, will only work if all his params are defaulted to the same value. – Rohi Mar 26 '18 at 12:12