66

As mentioned in PythonCookbook, * can be added before a tuple. What does * mean here?

Chapter 1.18. Mapping Names to Sequence Elements:

from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price'])
s = Stock(*rec) 
# here rec is an ordinary tuple, for example: rec = ('ACME', 100, 123.45)

In the same section, **dict presents:

from collections import namedtuple
Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
# Create a prototype instance
stock_prototype = Stock('', 0, 0.0, None, None)
# Function to convert a dictionary to a Stock
def dict_to_stock(s):
    return stock_prototype._replace(**s)

What is **'s function here?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
heLomaN
  • 1,634
  • 2
  • 22
  • 33
  • 1
    Please read [Python tutorial](http://docs.python.org/3/tutorial/). ([Unpacking Argument Lists](http://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists)) – falsetru Feb 16 '14 at 08:51
  • 1
    And it's not `**tuple` but `**dictionary`. – Martijn Pieters Feb 16 '14 at 08:53
  • @MartijnPieters SORRY for that, I will try to fix it. – heLomaN Feb 16 '14 at 09:05
  • No problem, just pointing to a misunderstanding on your part. – Martijn Pieters Feb 16 '14 at 09:07
  • 3
    @MartijnPieters This is not a duplicate question if you starting with the language. For me this question gave a different perspective then *arg and **kwargs. – Anurag Jain Jul 03 '18 at 00:24
  • @AnuragJain: How is it different? They both ask what `*` and `**` mean in the context of a function call. Being a duplicate is not merely asking a slightly different question, it has to be a question that would not lead to effectively identical answers. In both questions, the answer needed explains the same things. The answer here adds information not requested by the person who asked the question, which is fine, but the information requested here is a subset of what the other question requested. This is a great breadcrumb, but it's still a duplicate. – ShadowRanger Jan 31 '23 at 19:29

1 Answers1

176

In a function call

*t means "treat the elements of this iterable as positional arguments to this function call."

def foo(x, y):
    print(x, y)

>>> t = (1, 2)
>>> foo(*t)
1 2

Since v3.5, you can also do this in a list/tuple/set literals:

>>> [1, *(2, 3), 4]
[1, 2, 3, 4]

**d means "treat the key-value pairs in the dictionary as additional named arguments to this function call."

def foo(x, y):
    print(x, y)

>>> d = {'x':1, 'y':2}
>>> foo(**d)
1 2

Since v3.5, you can also do this in a dictionary literals:

>>> d = {'a': 1}
>>> {'b': 2, **d}
{'b': 2, 'a': 1}

In a function signature

*t means "take all additional positional arguments to this function and pack them into this parameter as a tuple."

def foo(*t):
    print(t)

>>> foo(1, 2)
(1, 2)

**d means "take all additional named arguments to this function and insert them into this parameter as dictionary entries."

def foo(**d):
    print(d)

>>> foo(x=1, y=2)
{'y': 2, 'x': 1}

In assignments and for loops

*x means "consume additional elements in the right hand side", but it doesn't have to be the last item. Note that x will always be a list:

>>> x, *xs = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3, 4]

>>> *xs, x = (1, 2, 3, 4)
>>> xs
[1, 2, 3]
>>> x
4

>>> x, *xs, y = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3]
>>> y
4

>>> for (x, *y, z) in [ (1, 2, 3, 4) ]: print(x, y, z)
...
1 [2, 3] 4

Note that parameters that appear after the starred parameter (the one marked *) are keyword-only:

def f(a, *, b): ...

f(1, b=2)  # fine
f(1, 2)    # error: b is keyword-only

Python3.8 added positional-only parameters, meaning parameters that cannot be used as keyword arguments. They appear before a / (a pun on * preceding keyword-only args).

def f(a, /, p, *, k): ...

f(  1,   2, k=3)  # fine
f(  1, p=2, k=3)  # fine
f(a=1, p=2, k=3)  # error: a is positional-only
Elazar
  • 20,415
  • 4
  • 46
  • 67
  • 1
    Nice answer. I'll just add keyword `operator` to make this answer easier to find when somebody searches for `python operator **` expecting `*` or `**` this is called operator in this context. – Mikko Rantalainen Jan 05 '21 at 13:49
  • 1
    Great answer. Just to add that in the case of "In a function signature" the common idiom is to use *args for positional arguments and **kwargs for keyword arguments. – Guzman Ojero Jan 26 '21 at 12:41
  • 1
    @GuzmanOjero this is true, but only if there is no meaningful alternative. – Elazar Jan 26 '21 at 16:28