10

A new "positional-only parameters" syntax has been introduced in 3.8.

From Positional-only parameters in the documentation:

There is new syntax (/) to indicate that some function parameters must be specified positionally (i.e., cannot be used as keyword arguments). This is the same notation as shown by help() for functions implemented in C (produced by Larry Hastings’ Argument Clinic tool).

Why ever use this syntax? Why is it better for the code's user?

It seems to me that this makes it harder for users to specify what their arguments actually mean, if they so desire. Why make it harder on the user?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Gulzar
  • 23,452
  • 27
  • 113
  • 201
  • 13
    Did you read the relevant [PEP](https://www.python.org/dev/peps/pep-0570/)? – Paul Rooney Oct 20 '19 at 22:28
  • 2
    Probably a similar reason to keyword-only arguments. If something should only be used in a certain way, allowing you to prevent potentially erroneous usage is good. – Carcigenicate Oct 20 '19 at 22:33
  • 2
    I would like to point out that SO guidelines encourages duplicating even all data on the internet into a form of Q&A. Having done that, the data is much more searchable, and endless docs and forum discussions can be avoided. – Gulzar Jun 21 '22 at 11:12

2 Answers2

22

To briefly summarize the stated rationales in PEP 570, the PEP that added positional-only arguments:

  1. Many built-in functions implemented in C already did not accept keyword arguments, even before Python 3.8. Allowing positional-only argument allows python code to be consistent with C code
  2. Some python classes, such as the constructor for the dict type, take arbitrary keyword arguments. If you were to try to define a class with such behavior in python, you would have to write def __init__(self, **kwds), ... except then you can't have a keyword argument named self!. Positional-only arguments can avoid this flaw.
  3. Some functions don't have any natural name to assign their argument to. Take the int constructor. int(x="3") is no more readable than int("3"). Positional-only arguments allow names that have no inherent meaning to be considered implementation details rather than part of the public API of the module.

There are a few more details in the PEP, but those three points summarize the general reason for the existence of the feature.

pppery
  • 3,731
  • 22
  • 33
  • 46
  • A good example for point 2 is [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial). You would not be able to fix an argument named `func` of the function you are passing if the argument `func` of `partial` was not keyword-only. – timgeb Jun 21 '22 at 10:17
-2

One reason is that people rename their function arguments and then all of the function calls which used keywords no longer work properly.

For example, given a function as follows:

def pow(base: float, exponent: int) -> float:
   pass

you could write function calls using positional or keyword arguments:

pow(4.5, 10)
pow(4.5, exponent=10)
pow(exponent=10, base=4.5)

If the arguments were subsequently renamed:

def pow(base: float, exp: int) -> float:
   """
        CHANGE LOG OR VERSION HISTORY:
           `exponent` renamed to `exp`
   """   
   pass 

then calls referring to the old argument names would give a TypeError:

pow(4.5, 10)  # OK
pow(4.5, exponent=10)  # TypeError
pow(exponent=10, base=4.5)  # TypeError

One potential rememdy is requiring consumers to use only positional arguments:

def pow(base: float, exponent: int, /) -> float:
    pass
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Toothpick Anemone
  • 4,290
  • 2
  • 20
  • 42