Any reason NOT to always use keyword arguments?

2019-01-30 07:55发布

Before jumping into python, I had started with some Objective-C / Cocoa books. As I recall, most functions required keyword arguments to be explicitly stated. Until recently I forgot all about this, and just used positional arguments in Python. But lately, I've ran into a few bugs which resulted from improper positions - sneaky little things they were.

Got me thinking - generally speaking, unless there is a circumstance that specifically requires non-keyword arguments - is there any good reason NOT to use keyword arguments? Is it considered bad style to always use them, even for simple functions?

I feel like as most of my 50-line programs have been scaling to 500 or more lines regularly, if I just get accustomed to always using keyword arguments, the code will be more easily readable and maintainable as it grows. Any reason this might not be so?

UPDATE:

The general impression I am getting is that its a style preference, with many good arguments that they should generally not be used for very simple arguments, but are otherwise consistent with good style. Before accepting I just want to clarify though - is there any specific non-style problems that arise from this method - for instance, significant performance hits?

11条回答
Rolldiameter
2楼-- · 2019-01-30 08:22

Keyword args are good when you have long parameter lists with no well defined order (that you can't easily come up with a clear scheme to remember); however there are many situations where using them is overkill or makes the program less clear.

First, sometimes is much easier to remember the order of keywords than the names of keyword arguments, and specifying the names of arguments could 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 wanting to generate a random int from [0,10) its clearer to write randint(10) than randint(low=10) in my view. If you need to generate an array with 100 numbers in [0,10) you can probably remember the argument order and write randint(0, 10, 100). However, you may not remember the variable names (e.g., is the first parameter low, lower, start, min, minimum) and once you have to look up the parameter names, you might as well not use them (as you just looked up the proper order).

Also consider variadic functions (ones with variable number of parameters that are anonymous themselves). E.g., you may want to write something like:

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

that can be applied a bunch of bare parameters (square_sum(1,2,3,4,5) # gives 55 ). Sure you could have written the function to take an named keyword iterable def square_sum(params): and called it like square_sum([1,2,3,4,5]) but that may be less intuitive, especially when there's no potential confusion about the argument name or its contents.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-30 08:23

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

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

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

create_user(
    first_name="George",
    last_name="Martin",
    contact_email="g.m@example.com",
    billing_email="payments@example.com",
    street_number="1",
    street_name="Radius Circle")
查看更多
该账号已被封号
4楼-- · 2019-01-30 08:28

Sometimes, things should be simple because they are simple.

If you always enforce you to use keyword arguments on every function call, soon your code will be unreadable.

查看更多
Deceive 欺骗
5楼-- · 2019-01-30 08:29

A mistake I often do is that I forget that positional arguments have to be specified before any keyword arguments, when calling a function. If testing is a function, then:

testing(arg = 20, 56)

gives a SyntaxError message; something like:

SyntaxError: non-keyword arg after keyword arg

It is easy to fix of course, it's just annoying. So in the case of few - lines programs as the ones you mention, I would probably just go with positional arguments after giving nice, descriptive names to the parameters of the function. I don't know if what I mention is that big of a problem though.

查看更多
Rolldiameter
6楼-- · 2019-01-30 08:32

One downside I could see is that you'd have to think of a sensible default value for everything, and in many cases there might not be any sensible default value (including None). Then you would feel obliged to write a whole lot of error handling code for the cases where a kwarg that logically should be a positional arg was left unspecified.

Imagine writing stuff like this every time..

def logarithm(x=None):
    if x is None:
        raise TypeError("You can't do log(None), sorry!")
查看更多
SAY GOODBYE
7楼-- · 2019-01-30 08:39

Well, there are a few reasons why I would not do that.

If all your arguments are keyword arguments, it increases noise in the code and it might remove clarity about which arguments are required and which ones are optionnal.

Also, if I have to use your code, I might want to kill you !! (Just kidding), but having to type the name of all the parameters everytime... not so fun.

查看更多
登录 后发表回答