How to implement "positional-only parameter" in a user defined function in python?

Question:

How can I implement “positional-only parameter” for a function that is user defined in python?

def fun(a, b, /):
    print(a**b)

fun(5,2)        # 25
fun(a=5, b=2)   # should show error
Asked By: Damodara Sahu

||

Answers:

Update: this answer will become increasingly out-dated; please see https://stackoverflow.com/a/56149093/1126841 instead.


The only solution would be to use a *-parameter, like so:

def fun(*args):
    print(args[0] ** args[1])

But this comes with its own problems: you can’t guaranteed the caller will provide exactly two arguments; your function has to be prepared to handle 0 or 1 arguments. (It’s easy enough to ignore extra arguments, so I won’t belabor the point.)

Answered By: chepner

Before Python 3.8, the / syntax was only documentational. Starting from 3.8, you can use it for specifying positional-only parameters in function definitions. Example:

def pow(x, y, z=None, /):
    r = x**y
    if z is not None:
        r %= z
    return r

Now pow(2, 10) and pow(2, 10, 17) are valid calls, but pow(x=2, y=10) and pow(2, 10, z=17) are invalid.

See PEP 570 for more details.

Answered By: Eugene Yarmash

Positional only arguments feature was added in python 3.8 after PEP 570 was accepted, before it was found in documentation in function signature to indicate function doesn’t take any keyword arguments.

Parameters in function definition prior Forward slash (/) are
positional only and parameters followed by slash(/) can be of any kind
as per syntax. Where arguments are mapped to positional only
parameters solely based on their position upon calling a function.
Passing positional-only parameters by keywords(name) is invalid.

Following example show function definition with positional only parameters

def foo(a, b, / , x, y):
   print("positional ", a, b)
   print("positional or keyword", x, y)

In the above function definition parameter a and b have to be passed as positional only arguments while x or y can be either positional or keyword.

Following function calls are valid

foo(40, 20, 99, 39)
foo(40, 3.14, "hello", y="world")
foo(1.45, 3.14, x="hello", y="world")

Following function call will raise an exception TypeError since a and be are passed as keyword arguments.

foo(a=1.45, b=3.14, x=1, y=4)

TypeError: foo() got some positional-only arguments passed as keyword
arguments: ‘a, b’

It is possible to define a function to accept positional only argument by adding forward slash (/) as last parameter in function definition.

def pow(x, y, /):
   return x ** y

In the above function definition all parameter (x and y) are positional only. Here, Passing arguments by their name not valid which will result in TypeError.

pow(2, 3); pow(3, 9) are valid while pow(x=3, y=9) is invalid which will raise TypeError

Answered By: neotam