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 list/tuple/set syntax:
>>> [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 dictionary syntax:
>>> 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)
{'x': 1, 'y': 2}
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, even if a tuple/set is used for assignment:
>>> w, *x = (1, 2, 3, 4)
>>> w
1
>>> x
[2, 3, 4]
>>> *x, y = (1, 2, 3, 4)
>>> x
[1, 2, 3]
>>> y
4
>>> w, *x, y = (1, 2, 3, 4)
>>> w
1
>>> x
[2, 3]
>>> y
4
>>> for (w, *x, y) in [ (1, 2, 3, 4) ]: print(w, x, y)
...
1 [2, 3] 4
More on function signatures
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
# TypeError: f() takes 1 positional argument but 2 were given
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
# TypeError: f() got some positional-only arguments passed as keyword arguments: 'a'
*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.