6

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
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Damodara Sahu
  • 115
  • 1
  • 8
  • If it's named, you can specify it as a keyword argument. The only option is to use a `*` argument to collected otherwise anonymous positional arguments. – chepner Oct 16 '18 at 16:24
  • Above program shows error. How to solve this problem? – Damodara Sahu Oct 16 '18 at 16:24
  • Functions with apparently anonymous positional parameters are implemented in C, not Python. – chepner Oct 16 '18 at 16:25
  • Python simply does not provide a way to define named, positional-only parameters. But why is it a problem to allow their values to be specified with keyword arguments? – chepner Oct 16 '18 at 16:26
  • But, in python site i found the syntax of positional-only parameters. – Damodara Sahu Oct 16 '18 at 16:34
  • Those are built-in functions (`builtin_function_or_method`), not user-defined functions (`function`). They are implemented in C, and there is a library (whose name escapes me at the moment) that assists in defining such functions. One of its features, I believe, allows for positional arguments whose names aren't exposed at the Python level. – chepner Oct 16 '18 at 16:47
  • [Argument Clinic](https://docs.python.org/3/howto/clinic.html), I think, is what I was thinking of. (But again, it's for functions written in C, not Python.) – chepner Oct 16 '18 at 16:56
  • Ok, i got it. thnq. – Damodara Sahu Oct 16 '18 at 17:19
  • this will be possible in a (currently) future version of Python https://discuss.python.org/t/pep-570-python-positional-only-parameters/1078/149 – Anentropic May 14 '19 at 16:44

3 Answers3

9

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.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • This right here. Was experimenting with some CPython library code from GitHub and I was wondering why the interpreter keeps complaining about this notation. Turns out I'm only on 3.7 but the master branch in GH is already showing the 3.8 code. – skytreader Dec 15 '19 at 04:52
4

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.)

chepner
  • 497,756
  • 71
  • 530
  • 681
1

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

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
neotam
  • 2,611
  • 1
  • 31
  • 53