Any reason NOT to always use keyword arguments?

Before moving to python, I started with some Objective-C / Cocoa books. As far as I remember, most functions required that keyword arguments be explicitly specified. Until recently, I completely forgot about it and just used positional arguments in Python. But lately, I have come across several errors that have arisen due to incorrect positions - mean little things.

I thought - generally speaking, if there is no circumstance that specifically requires arguments other than the keyword, is there any good reason NOT to use the keyword arguments? It is believed that this is a bad style that they always use, even for simple functions?

It seems to me that since most of my 50-line programs regularly scale to 500 or more lines, if I'm just used to always using keyword arguments, the code will be easier to read and maintain as it grows. For some reason this may not be the case?

UPDATE:

The general impression I get is that he prefers style, with a lot of good arguments, that they usually should not be used for very simple arguments, but otherwise they are in good style. Before accepting, I just want to clarify if there are any specific non-style issues that arise from this method - for example, significant performance gains?

+51
python coding-style
Aug 12 2018-11-11T00:
source share
10 answers

There is no reason not to use keyword arguments other than code clarity and readability. The choice of whether to use keywords should be based on whether the keyword adds additional useful information when reading the code or not.

Following the following general rule:

  • If it is difficult to determine the function (name) of an argument from the name of the function, pass it by keyword (for example, I would not want to have text.splitlines(True) in my code).
  • If it is difficult to determine the order of the arguments, for example, if you have too many arguments or when you have independent optional arguments, pass it by keyword (for example, funkyplot(x, y, None, None, None, None, None, None, 'red') doesn't look particularly nice).
  • Never skip the first few arguments for a keyword if the purpose of the argument is obvious. You see, sin(2*pi) better than sin(value=2*pi) , the same is true for plot(x, y, z) .

In most cases, stable required arguments would be positional, and a keyword would be optional arguments.

There is also a possible difference in performance, since in each implementation the keyword arguments will be a little slower, but considering this, as a rule, premature optimization and the results from it would not be significant, I do not think it is important for a decision.

UPDATE: non-steric problems

Keyword arguments can do everything that positional arguments can have, and if you define a new API, there are no technical flaws besides possible performance issues. However, you may have minor problems if you combine your code with existing elements.

Consider the following:

  • If you force your function to accept keyword arguments, this becomes part of your interface. You cannot replace your function with another one that has a similar signature, but a different keyword for the same argument.
  • You might want to use a decorator or other utility for your function, which assumes your function takes a positional argument. Unbound methods are an example of such a utility because they always pass the first argument as positional after reading it as positional, so cls.method(self=cls_instance) does not work, even if there is a self argument in the definition.

None of these problems will be a real problem if you have developed your API well and documented the use of keyword arguments, especially if you are not developing something that should be interchangeable with what already exists.

+50
Aug 12 2018-11-12T00:
source share

If you want to improve readability of function calls, why not just declare functions as normal, for example.

 def test(x, y): print "x:", x print "y:", y 

And just call the functions by declaring the names explicitly, for example:

 test(y=4, x=1) 

Which clearly gives you the result:

 x: 1 y: 4 

or this exercise would be pointless.

This avoids the presence of arguments and optional default values ​​(if you do not want them to be, in which case just use the keyword arguments! :) and gives you all the flexibility and improved readability of the named arguments, which are not limited by order.

+16
Aug 12 2018-11-11T00:
source share

Well, there are several reasons why I did not.

If all arguments are keyword arguments, this increases the noise level in the code, and this can lead to clarity as to which arguments are needed and which of them are optional.

Also, if I need to use your code, I might want to kill you! (Just kidding), but every time you need to enter the name of all the parameters ... not so much fun.

+11
Aug 12 2018-11-11T00:
source share

I remember reading a very good explanation of the "options" in UNIX programs: "Parameters must be optional, the program should work without any options."

The same principle can apply to keyword arguments in Python. Such arguments should allow the user to "customize" the function call, but the function should be called without any implicit argument value pairs of the word.

+6
Aug 12 2018-11-12T00:
source share

Just to offer a different argument, I think there are some cases where named parameters can improve readability. For example, imagine a function that creates a user on your system:

 create_user("George", "Martin", "gm@example.com", "payments@example.com", "1", "Radius Circle") 

From this definition, it is not at all clear what these values ​​mean, even if they are all required, however with named parameters this is always obvious:

 create_user( first_name="George", last_name="Martin", contact_email="gm@example.com", billing_email="payments@example.com", street_number="1", street_name="Radius Circle") 
+5
Aug 12 2018-11-12T00:
source share

When the built-in compile() and __import__() Python functions get support for keyword arguments , the same argument was made in favor of clarity. It seems that no significant increase in performance is observed.

Now, if you do your functions, accept only keyword arguments (as opposed to passing positional parameters using keywords when they are called, which is allowed), then yes, it will be annoying.

+4
Aug 12 2018-11-12T00:
source share

Sometimes things have to be simple because they are simple.

If you always apply keyword arguments to the use of each function call, your code will soon be unreadable.

+3
Aug 12 '11 at 2:56 a.m.
source share

I don’t see the purpose of using keyword arguments when the meaning of the arguments is obvious.

+3
Aug 12 '11 at 3:01 a.m.
source share

One drawback that I saw is that you have to think of a reasonable default value for everything, and in many cases there cannot be a reasonable default value (including None ). Then you would have to write whole error handling code for cases where kwarg, which should logically be a positional argument, remains unspecified.

Imagine writing things like that every time.

 def logarithm(x=None): if x is None: raise BadArgsException("You can't do log(None), silly!") 
+3
Aug 12 2018-11-11T00:
source share

Keyword arguments are good when you have a long list of parameters without a clearly defined order (that you cannot easily find a clear outline for remembering); however, there are many situations where their use is excessively large or makes the program less clear.

First, it is sometimes much easier to remember the order of keywords than the names of the keyword arguments, and specifying the names of the arguments can make it less clear. Take randint from scipy.random with the following docstring:

 randint(low, high=None, size=None) Return random integers x such that low <= x < high. If high is None, then 0 <= x < low. 

When you want to generate a random int from [0.10), it is clearer to write randint(10) than randint(low=10) in my opinion. If you need to create an array with 100 numbers in [0.10), you can probably remember the order of the arguments and write randint(0, 10, 100) . However, you may not remember the names of the variables (for example, this is the first parameter: low, lower, initial, minimum, minimum), and as soon as you have to look for the names of the parameters, you can also not use them (since you were just looking for the proper order).

We also consider variational functions (those that have a variable number of parameters that are anonymous themselves). For example, you can write something like:

 def square_sum(*params): sq_sum = 0 for p in params: sq_sum += p*p return sq_sum 

which can be applied to empty parameters ( square_sum(1,2,3,4,5) # gives 55 ). Of course, you could write a function to take the named keyword iterable def square_sum(params): and call it square_sum([1,2,3,4,5]) , but this may be less intuitive, especially when not no confusion about the name of the argument or its contents.

+2
Aug 12 2018-11-21T00:
source share



All Articles