HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonCriticalCanonical

What do ** (double star/asterisk) and * (star/asterisk) mean in a function call?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
doublefunctionandstarmeancallwhatasterisk

Problem

In code like zip(x) or f(k), what do the and respectively mean? How does Python implement that behaviour, and what are the performance implications?

See also: Expanding tuples into arguments. Please use that one to close questions where OP needs to use * on an argument and doesn't know it exists. Similarly, use Converting Python dict to kwargs? for the case of using **.

See What does ** (double star/asterisk) and * (star/asterisk) do for parameters? for the complementary question about parameters.

See What do ** (double star/asterisk) and * (star/asterisk) inside square brakets mean for class and function declarations in Python 3.12+? for the complementary question when used for type parameters.

Solution

A single star * unpacks a sequence or collection into positional arguments. Suppose we have

def add(a, b):
    return a + b

values = (1, 2)


Using the unpacking operator, we can write s = add(values), which will be equivalent to writing s = add(1, 2).

The double star ** does the same thing for a dictionary, providing values for named arguments:

values = {'a': 1, 'b': 2}
s = add(**values) # equivalent to add(a=1, b=2)


Both operators can be used for the same function call. For example, given:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = {'c': 10, 'd': 15}


then s = add(*values1, **values2) is equivalent to s = sum(1, 2, c=10, d=15).

See also the relevant section of the tutorial in the Python documentation.

Similarly, and ** can be used for parameters. Using allows a function to accept any number of positional arguments, which will be collected into a single parameter:

def add(*values):
    s = 0
    for v in values:
        s = s + v
    return s


Now when the function is called like s = add(1, 2, 3, 4, 5), values will be the tuple (1, 2, 3, 4, 5) (which, of course, produces the result 15).

Similarly, a parameter marked with ** will receive a dict:

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1


this allows for specifying a large number of optional parameters without having to declare them.

Again, both can be combined:

def add(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = add(1, 2, 3, 4, 5)            # returns 15
s = add(1, 2, 3, 4, 5, neg=True)  # returns -15
s = add(1, 2, 3, 4, 5, neg=False) # returns 15

Code Snippets

def add(a, b):
    return a + b

values = (1, 2)
values = {'a': 1, 'b': 2}
s = add(**values) # equivalent to add(a=1, b=2)
def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = {'c': 10, 'd': 15}
def add(*values):
    s = 0
    for v in values:
        s = s + v
    return s
def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

Context

Stack Overflow Q#2921847, score: 1217

Revisions (0)

No revisions yet.