Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the pythonic way to pass arguments to functions?

Tags:

python

I'm working on a project that almost everywhere arguments are passed by key. There are functions with positional params only, with keyword (default value) params or mix of both. For example the following function:

def complete_task(activity_task, message=None, data=None):
    pass

This function in the current code would be called like this:

complete_task(activity_task=activity_task, message="My massage", data=task_data)

For me there is no point to name arguments whose name is obvious by the context of the function execution / by the variable names. I would call it like this:

complete_task(activity_task, "My message", task_data)

In certain cases where it's not clear what the a call argument is from the context, or inferred from the variable names, I might do:

complete_task(activity_task, message="success", task_data=json_dump)

So this got me wondering if there is a convention or "pythonic" way to call functions with positional/keyword params, when there is no need to rearrange method arguments or use default values for some of the keyword params.

like image 878
ddinchev Avatar asked May 10 '16 02:05

ddinchev


People also ask

How can we pass arguments to functions in C++?

The call by value method of passing arguments to a function copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument. By default, C++ uses call by value to pass arguments.


2 Answers

The usual rules of thumb I follow are:

  1. Booleans, particularly boolean literals, should always be passed by keyword unless it is really obvious what they mean. This is important enough that I will often make booleans keyword-only when writing my own functions. If you have a boolean parameter, your function may want to be split into two smaller functions, particularly if it takes the overall structure of if boolean_parameter: do_something(); else: do_something_entirely_different().
  2. If a function takes a lot of optional parameters (more than ~3 including required parameters), then the optionals should usually be passed by keyword. But if you have a lot of parameters, your function may want to be refactored into multiple smaller functions.
  3. If a function takes multiple parameters of the same type, they probably want to be passed as keyword arguments unless order is completely obvious from context (e.g. src comes before dest).
  4. Most of the time, keyword arguments are not wrong. If you have a case where positional arguments are confusing, you should use keyword arguments without a second thought. With the possible exception of simple one parameter functions, keyword arguments will not make your code any harder to read.
like image 113
Kevin Avatar answered Oct 22 '22 03:10

Kevin


Python has 2 types of arguments1. positional and keyword (aka default). The waters get a little muddy because positional arguments can be called by keyword and keyword arguments can be called by position...

def foo(a, b=1):
   print(a, b)

foo(1, 2)
foo(a=1, b=2)

With that said, I think that the names of the types of arguments should indicate how you should (typically) use them. Most of the time, I see positional arguments called by position and keyword arguments called by keyword. So, if you're looking for a general rule of thumb, I'd advise that you make the function call mimic the signature. In the case of our above foo function, I'd call it like this:

foo(1, b=2)

I think that one reason to follow this advice is because (most of the time), people expect keyword arguments to be passed via keyword. So it isn't uncommon for someone to later add a keyword:

def foo(a, aa='1', b=2):
    print(a, aa, b)

If you were calling the function using only positional arguments, you'd now be passing a value to a different parameter than you were before. However, keyword arguments don't care what order you pass them, so you should still be all set.

So far, so good. But what rules should you use when you're creating a function? How do you know whether to make an argument a default argument or a positional argument? That's a reasonable question -- And it's hard to find a good rule of thumb. The rules of thumb I use are as follows:

  1. Be consistent with the rest of the project -- It's hard to get it right if you're doing something different than the rest of the surrounding code.
  2. Make an argument a default argument if (and only if) it is possible to supply a reasonable default. If the function will fail if the user doesn't supply a particular argument (because there is no good default), then it should be positional.

1Python3.x also has keyword only arguments. Those don't give you a choice, so I don't know that they add too much to the discussion here :-) -- Though I don't know that I've seen their use out in the wild too much.

like image 23
mgilson Avatar answered Oct 22 '22 03:10

mgilson