Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Positional-Only Arguments

In this lesson, you’ll learn about how to add positional-only arguments to your functions in Python 3.8.

The built-in function float() can be used for converting text strings and numbers to float objects. Consider the following example:

>>> float("3.8")

>>> help(float)
class float(object)
 |  float(x=0, /)
 |  Convert a string or number to a floating point number, if possible.


Look closely at the signature of float(). Notice the slash (/) after the parameter. What does it mean?

It turns out that while the one parameter of float() is called x, you’re not allowed to use its name:

>>> float(x="3.8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: float() takes no keyword arguments

When using float(), you’re only allowed to specify arguments by position, not by keyword. Before Python 3.8, such positional-only arguments were only possible for built-in functions. There was no easy way to specify that arguments should be positional-only in your own functions:

>>> def incr(x):
...     return x + 1
>>> incr(3.8)

>>> incr(x=3.8)

In Python 3.8, you can use / to denote that all arguments before it must be specified by position. You can rewrite incr() to only accept positional arguments:

>>> def incr(x, /):
...     return x + 1
>>> incr(3.8)

>>> incr(x=3.8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: incr() got some positional-only arguments passed as
           keyword arguments: 'x'

By adding / after x, you specify that x is a positional-only argument. You can combine regular arguments with positional-only ones by placing the regular arguments after the slash:

>>> def greet(name, /, greeting="Hello"):
...     return f"{greeting}, {name}"
>>> greet("Christopher")
'Hello, Christopher'

>>> greet("Christopher", greeting="Awesome job")
'Awesome job, Christopher'

>>> greet(name="Christopher", greeting="Did it work?")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    greet(name="Christopher", greeting="Did it work?")
TypeError: greet() got some positional-only arguments passed as
           keyword arguments: 'name'

In greet(), the slash is placed between name and greeting. This means that name is a positional-only argument, while greeting is a regular argument that can be passed either by position or by keyword.

At first glance, positional-only arguments can seem a bit limiting and contrary to Python’s mantra about the importance of readability. You may find that there are not a lot of occasions where positional-only arguments improve your code.

However, in the right circumstances, positional-only arguments can give you some flexibility when you’re designing functions. First, positional-only arguments make sense when you have arguments that have a natural order but are hard to give good, descriptive names to.

Another possible benefit of using positional-only arguments is that you can more easily refactor your functions. In particular, you can change the name of your parameters without worrying that other code depends on those names.

Positional-only arguments nicely complement keyword-only arguments. In any version of Python 3, you can specify keyword-only arguments using the star (*). Any argument after * must be specified using a keyword:

>>> def to_fahrenheit(*, celsius):
...     return 32 + celsius * 9 / 5
>>> to_fahrenheit(40)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: to_fahrenheit() takes 0 positional arguments but 1 was given

>>> to_fahrenheit(celsius=40)

celsius is a keyword-only argument, so Python raises an error if you try to specify it based on position, without the keyword.

You can combine positional-only, regular, and keyword-only arguments by specifying them in this order separated by / and *. In the following example, text is a positional-only argument, border is a regular argument with a default value, and width is a keyword-only argument with a default value:

>>> def headline(text, /, border="~", *, width=50):
...     return f" {text} ".center(width, border)

Since text is positional-only, you can’t use the keyword text:

>>> headline("Positional-only Arguments")
'~~~~~~~~~~~ Positional-only Arguments ~~~~~~~~~~~~'

>>> headline(text="This doesn't work!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: headline() got some positional-only arguments passed as
           keyword arguments: 'text'

border, on the other hand, can be specified both with and without the keyword:

>>> headline("Python 3.8", "=")
'=================== Python 3.8 ==================='

>>> headline("Real Python", border=":")
':::::::::::::::::: Real Python :::::::::::::::::::'

Finally, width must be specified using the keyword:

>>> headline("Python", "@", width=38)
'@@@@@@@@@@@@@@@ Python @@@@@@@@@@@@@@@'

>>> headline("Python", "@", 38)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    headline("Python", "@", 38)
TypeError: headline() takes from 1 to 2 positional arguments
           but 3 were given

For more details on this topic, check out the following resources:

  • PEP 457 provides an in-depth discussion on the / notation.
  • PEP 570 gives more details on Python positional-only parameters.

Ihor Udod on Jan. 9, 2020

How do you achieve this highlighting in VS Code terminal?

Chris Bailey RP Team on Jan. 10, 2020

Hi @Ihor Udod, I’m using the REPL replacement named BPython, I have links and more information about it in the previous lesson, below the video.

Ihor Udod on Jan. 10, 2020

Thank you Chris!

agbehiogiri on March 30, 2020

Hello Chris, bpython seems not to work on a Windows platform.

Denis Roy on March 30, 2020

@agbehiogiri: it is reported that bpython can work on Windows but only after jumping through a few hoops. See the documentation for the details.

Chris Bailey RP Team on March 31, 2020

Hi @agbehiogiri and @Denis Roy, Denis is correct that it requires some hoop jumping to make it work on Windows.

bPython was created under Linux originally, and making it work with macOS wasn’t that different. The issue revolves around bPython using/depending on “Curses”. The consensus after some searching seems to be that you can use this package, windows-curses. You would need to install it via pip, python3 -m pip install windows-curses.

You will also not be able to type just bpython in your terminal application. You would instead use python3 -m bpython.cli. I was able to get this to work on a windows 10 installation yesterday. It warns that the Command Line Interface will be deprecated at some point, so not sure what that means as far as long term support. The other method mentioned in some posts is running bpython by typing bpython-curses.exe. I could not get that to work.

One additional issue you may have is something to do with saving the history, and it crashing on first time running. Here is a link to a stack overflow thread with a solution if that happens to you. It is the first answer with Set-Content -Path...

Overall after doing the research, I think maybe IPython is a much easier solution. Very similar, and has it’s own benefits.

I hope this helps.

djlondon on April 26, 2020

Struggling to see a real use case of this. The examples shown highlight how it could be used, but I’d need a really stellar reason to use this to overcome the readability hit. It’s rather cryptic, reminding me of C++!

djlondon on April 26, 2020

Update prior to my original comment

This section of PEP 570 is does a pretty good job at explaining desirable use cases.

Dan Bader RP Team on May 29, 2020

Regarding alternative REPLs, if bpython is difficult to install I can also recommend ptpython. Chris’s recommendation of IPython is also great!

widowmakerreborn on July 7, 2020

most useless feature. The idea of having a name of argument is exactly to reflect calling side intention. I don’t see how why people want to shoot in their leg with this feature.

widowmakerreborn on July 7, 2020

Another problem with position-only arguments is a type of exception -TypeError, why not a ValueError?

Become a Member to join the conversation.