Register to get access to free programming courses with interactive exercises

More about named arguments Python: Functions

We can retrieve positional and named arguments in any number of *args.

Getting named arguments as dictionaries

Only named arguments can be obtained as a dictionary, which allows you to store the names in keys:

def g(**kwargs):
    return kwargs

g(x=1, y=2, z=None)
# {'x': 1, 'y': 2, 'z': None}

We can refer to an argument that receives this dictionary as kwargs (keyword arguments).

We write the keyword arguments after all the usual positional ones:

  • *args before the first argument with the default value
  • **kwargs after the last argument with the default value

Let us define a function that takes all kinds of arguments:

def f(x, y, *args, kx=None, ky=42, **kwargs):
    return (x, y, args, kx, ky, kwargs)

f(1, 2, 3, 4, kx='a', ky='b', kz='c')
# (1, 2, (3, 4), 'a', 'b', {'kz': 'c'})

Do not worry. It is rare for a function to use all of these features in real-life code. Nevertheless, it is essential to understand how each type of argument declaration works and how to combine them.

Passing named arguments using dictionaries

As with positional arguments, named arguments can be passed to a function in bulk as a dictionary. To do this, you should put two asterisks before the dictionary. Here is an example:

def coords(x, y):
    return (x, y)

coords(x=1, **{'y': 2})
# (1, 2)

As you can see, we also specified the regular named and wrapped arguments in a dictionary. It is both possible and convenient. Let us try to call the function f from the example at the beginning of the lesson with two sets of arguments:

  • The first one is for positional arguments
  • The second one is for named ones

Here is the code:

positional = (2, 3)
named = dict(ky='b', kz='c')
f(1, *positional, 4, kx='a', **named)
# (1, 2, (3, 4), 'a', 'b', {'kz': 'c'})

Notice how we constructed the dictionary. We did not write a literal. So, the dictionary looks even more like a stored set of arguments because we called the dict function with several named arguments.

You should also note that when replacing, these unfolding sets of arguments can be specified along with the corresponding type:

  • *positional with positional arguments
  • **named with named ones

Moreover, any named arguments must come after any positional arguments.

Using keyword-only arguments

Python 3 added the ability to mark the named arguments. So, we can call functions by passing those arguments by name. We can refer to them as keyword-only arguments.

We cannot pass them to the function as positional arguments. Here is an example:

def open_file(name, *, writable=False, binary=False):
    …

f1 = open_file('foo.txt', writable=True)
f2 = open_file('bar.bin', binary=True)
f3 = open_file('raw.dat', True, True)
# TypeError: `open_file()` takes 1 positional argument, but 3 were given

The * separates ordinary arguments we can specify by name and position from strictly named arguments. This separator can only be used once in a single definition. And we cannot use it in functions with *args.

It is not logical, but that is how it happened. You can declare functions that take only strictly named arguments, but you should put an asterisk at the beginning of the argument list.

This example shows a way to describe arguments. The first argument is the name of the file to open. The file name is always present because you need to open something. Moreover, we usually associate its meaning with the function name. Therefore, this argument cannot be named.

But writable and binary are optional arguments. Which also take the seemingly meaningless values True and False. We will not please many people with a call open_file('raw.dat', True, True). Therefore, we declare the options such we can only give them explicitly.

Calling functions and the order of arguments

When calling functions, we have more freedom to set the order. We can mix single-named arguments with substitutions for positional sets. Here is an example of such a call:

foo = [1, 2, 3]
bar = "abc"
# The function `f` is the same as in the first section of the lesson
f(kx=42, *foo, ky=100, *bar)
# (1, 2, (3, 'a', 'b', 'c'), 42, 100, {})

Let us talk about another feature. It is a function with a signature like f(x, *args) where we cannot specify the x argument by name and expand the parameter set simultaneously. You cannot do anything like this: f(*foo, x=42).


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

Bookmate
Health Samurai
Dualboot
ABBYY
Suggested learning programs
profession
new
Developing web applications with Django
10 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.