Python Position and Keyword Only Arguments
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.