2

Keyword-only arguments are arguments that can only be supplied to a function by keyword. In Python they are defined by a single asterisk in a function's signature. For example:

>>> def foo(bar, *, baz):
        print(bar, baz)
>>> foo(1, baz=2)
    1 2
>>> foo(1, 2)
TypeError: foo() takes 1 positional argument but 2 were given

Using them has not only stylistic advantages and disadvantages but functional as well. Here are some that I'm aware of:

Advantages:

And disadvantages:

  • Making all arguments keyword-only won't allow to use the function with map. For example:

    >>> def square(*, x):
            return x * 2
    
    >>> list(map(square, [1, 2, 3]))
    TypeError: square() takes 0 positional arguments but 1 was given
    

I couldn't find a general description on how I should properly use the keyword-only arguments in PEP 3102 that proposed them in the first place or in any other sources.

So, my questions are: Are there any other pitfalls that I'm unaware of when using keyword-only arguments? How can I safely use them without potentially break something in the future?

0

3 Answers 3

6
+250

Indeed, language features have pitfalls, costs, and benefits. The core point of programming language style guides (such as Google Style Guides) and JavaScript: The Good Parts is to avoid features or uses that are surprising, error-prone, tricky, or hard to maintain.

Here are some good cases for keyword-only args:

  • Options that are non-obvious at the call site, esp. boolean flags and multiple options. For io.open(), it would be reasonable (except for backwards compatibility) to make all the arguments after file and mode be keyword-only:
    io.open(file, 'r', 0, None, '', '', False)
  • Arguments that are not easy to keep straight:
    def address(*, country, administrative_area, sub_administrative_area, locality, dependent_locality, postal_code, thoroughfare, premise)
  • Arguments that you want to require callers to pass explicitly:
    def delete(base, *, recursive)
  • Options to a function that also takes varargs:
    def send(topic, message, *values, debug=True)
  • Options to a function that might well take varargs in the future. This is definitely a judgement call. The point is adding a varargs parameter will break any callers that pass an option as a positional parameter. Defining the options as keyword-only parameters reserves the ability to add a varags parameter.
    def send(topic, message, *, debug=True)

Here are some cases to not use keyword-only args:

  • Code that needs to be compatible with Python 2.
  • Generic functional programming: map(), filter(), apply(), ...
  • One-argument functions: repr(object).
  • Varargs: max(x, y, z, t).
  • Where keyword-only args would add verbosity and clutter to no advantage: bitwise_and(x1, x2). [numpy.bitwise_and() takes those two arguments and a bunch of optional arguments that are fair game for keyword-only, except for compatibility.]

and some other pitfalls of keyword-only args:

  • It's yet another feature for new team members to learn when they're coming up to speed on Python and your code base.
  • Extra complexity and distraction in the function definition. (What's that *?)
  • Some dev tools might not handle it well: syntax highlighters, diff tools, refactoring editors, code inspectors, C interop, RPC (remote procedure call) code generators, ...
  • Language features can interact with each other in surprising ways. "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery.
2

Keyword-only arguments are just a tool and there is no one perfect tool for everything. When it doesn't work, like in case of map, you use positional arguments.

You can use keyword-only arguments safely. Changing code, refactoring, is common way of handling with worries about future. Instead of predicting future you adapt past to current needs.

Best practice for keyword-only arguments is answer of Personal preferences and Software design.

Random result from internet search: 4 Best Practices for Function Arguments http://www.informit.com/articles/article.aspx?p=2314818

1

There are no special disadvantages to using keyword-only arguments.

True, your function will have a different signature to ones with positional arguments and thus wont work with other functions that expect to be passed functions which match a particular signature.

But that is true for any incompatible change in signature and is easily worked around by wrapping your function.

You could if you wished also write a map function which inspects the arguments and uses the first keyword argument, when this case occurs.

Although I think I would argue that it is nonsensical for a function with a single argument to force the use of a keyword and throwing the error makes as much sense as implementing this behavior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.