Codementor Events

Python Position and Keyword Only Arguments

Published Mar 21, 2023

What does / and * mean in a Python function definition mean

Recently when I was teaching PythonToProject bootcamp, one of my students had a question about Python's __new__ function. __new__ The function lets you manipulate how you create your objects. That wasn't what caught my eye.

We all know about *args and **kwargs in function calls. But have you seen something like these

def new_function(x, /, y, z):
  pass
def new_function_1(x, y, z, *, scale):
  pass

You can use the help method to understand any object, class, or function in Python. To show my students that __new__ and __init__ are default constructs that are available even in builtin classes like int or float I ran the following in the Python shell

help(int) # will show that int is a class 


help(int.__new__) # will show that a __new__ method exists
>>> help(int.__new__)

Help on built-in function __new__:

__new__(*args, **kwargs) method of builtins.type instance
    Create and return a new object.  See help(type) for an accurate signature.
(END)

When I ran it for __init__

help(int.__init__) # BOOM! I learned something new. 

Help on wrapper_descriptor:

__init__(self, /, *args, **kwargs)
    Initialize self.

The __init__ (self, /, *args, **kwargs) line. What is that / doing in the middle of the function definition? You can also replace / it with * and these are two new features introduced in 3.8

To enforce that a function accepts certain arguments only based on their position and not by their name, you mention them in the function definition and follow it up with a /.All arguments following the / can be positional or keyword based

A good use case for this is cases where the position of the argument means something.

def point(x, y, z, /, scale=1):
    pass

For the above function, if you pass point(x=10, y=20, z=30) will raise an error

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

Here is a bonus example for you.

def rgb_to_hex(r, g, b, /):
    pass

Keyword Only Arguments

Similarly, you can enforce a function to pass keyword-only args by prepending the list of args with a * -PEP3102

All arguments before the * can be positional. Python's sorted method is a wonderful example for this. It uses both keyword and positional args.

def sorted(iterable, /, *, key=None, reverse=False)
  ...

When you pass keyword-only args as positional args, the function will behave as if an unknown argument is passed

Traceback (most recent call last):
 File "\<stdin\>", line 1, in \<module\>
TypeError: sorted expected 1 argument, got 2

Next time when you write an function and want to enforce the users to use position or keyword based arguments, you know how to implement it.

Discover and read more posts from Bhavani Ravi
get started