Python unpacking operator (*)
This is Iterable Unpacking. You may have seen it in other places to assign values to multiple variables from a single expression
a, b, c = [1, 2, 3]
This syntax includes a *
to indicate that this variable should be a list containing the elements from the iterable that weren't explicitly assigned to another variable.a, *b, c = [1, 2, 3, 4, 5]
print(b)
# [2, 3, 4]
So, what's going on in your example? There's only a single variable name being assigned to, so it's going to take all the items not assigned to another variable, which in this case is all of them. If you try just*s='abcde'
you'll get SyntaxError: starred assignment target must be in a list or tuple
Which is why that comma is there, as a trailing comma is how you indicate a single-value tuple. How are python's unpacking operators * and ** used?
Around 1992 (not sure about Python version). This is from the Grammar file of Python 1.0.1.
# 06-Apr-92:
# Use only '*' for varargs list
# 31-Mar-92:
# Tighten syntax for try statements
# 27-Feb-92:
# Allow NEWLINE* after eval input
# 16-Jan-92:
# Added '*' as alternative for '+' in varargs syntax
# (Not sure which alternative is better yet.)
# 11-Jan-92:
# Variable length argument list syntax added: def f(a, b, +rest): ...
Python 1.4+:Python 1.6+Keyword Arguments: Functions and methods written in Python can now be
called using keyword arguments of the formkeyword = value
.
Python <= 2.7:There's now special syntax that you can use instead of the
apply()
function.f(*args, **kwds)
is equivalent toapply(f, args, kwds)
. You
can also use variationsf(a1, a2, *args, **kwds)
and you can leave one
or the other out:f(*args)
,f(**kwds)
.
Tuple parameter unpacking was removed in Python 3.0.
Python 3.0+PEP 3113: Tuple parameter
unpacking removed. You can no longer writedef foo(a, (b, c)): ...
.
Usedef foo(a, b_c): b, c = b_c
instead.
Python 3.5+PEP 3132: Extended Iterable
Unpacking. You can now write things likea, b, *rest =
. And even
some_sequence*rest, a = stuff
. The rest object is always
a (possibly empty) list; the right-hand side may be any iterable.PEP 3102: Keyword-only arguments. Named parameters occurring after
*args
in the parameter list must be specified using keyword syntax in the call. You can also use a bare*
in the parameter list to indicate
that you don’t accept a variable-length argument list, but you do have
keyword-only arguments
PEP 448, additional
unpacking generalizations.
As far as I know there's no single page that lists all the syntax changes. Per version syntax changes are listed in the What's new in Python section or you could check the Grammar specification of each release to see the differences.
Dictionary Unpacking Operator **
My guess is because if we want this **kwargs
to work, we have to have keyword-argument on the right hand side(It should be converted to dictionary) just like you did :
required, *args, **kwargs = "Welcome to...", 1, 2, 3, site='stackoverflow.com'
But as we know right hand side of an assignment is evaluated fist(then the unpacking occurs). so in this case you can think of an another assignment in an expression which is invalid. for example :a = (1, 2, 3) # Valid
b = (1, 2, var=20) # Invalid
By looking at:from dis import dis
dis('a, b, c = 5, 4, 3')
1 0 LOAD_CONST 0 ((5, 4, 3))
2 UNPACK_SEQUENCE 3
4 STORE_NAME 0 (a)
6 STORE_NAME 1 (b)
8 STORE_NAME 2 (c)
10 LOAD_CONST 1 (None)
12 RETURN_VALUE
Python tries to build a tuple from right hand side of the assignment, you can't have an assignment statement in there. I think same thing is happened and that's the reason. Python: Splat/unpack operator * in python cannot be used in an expression?
Unpacking in list, dict, set, and tuple literals has been added in Python 3.5
, as described in PEP 448:
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) on Windows (64 bits).
>>> [1, 2, 3, *[4, 5, 6]]
[1, 2, 3, 4, 5, 6]
Here are some explanations for the rationale behind this change. Note that this does not make *[1, 2, 3]
equivalent to 1, 2, 3
in all contexts. Python's syntax is not intended to work that way. How to use unpacking operator (*) together with C-style string formatting?
%
takes a tuple, so you can write
names = "Looking for %s, %s, %s" % tuple(L)
If format requires a single argument, values may be a single non-tuple object. Otherwise, values must be a tuple with exactly the number of items specified by the format string, or a single mapping object (for example, a dictionary).If you still want to use unpacking— https://docs.python.org/3/library/stdtypes.html#old-string-formatting
*
, you can donames = "Looking for %s, %s, %s" % (*L,)
although this is just a convoluted way of writing tuple(L)
in this case; see PEP 448. Note that ,
cannot be omitted. proper name for python * operator?
In Ruby and Perl 6 this has been called "splat", and I think most people from
those communities will figure out what you mean if you call it that.
The Python tutorial uses the phrase "unpacking argument lists", which is
long and descriptive.
It is also referred to as iterable unpacking, or in the case of **
,
dictionary unpacking.
Is there a way to define a pair of tuple as argument of a function ? I'm stucked with this tuple parameter unpacking is not supported in Python 3
You can rewrite your function and do tuple unpacking in function body (as stated in official PEP 3113 -- Removal of Tuple Parameter Unpacking). For example:
def distance_points(p1, p2):
(x1, y1), (x2, y2) = p1, p2
dist = ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
return dist
print(distance_points((1.0, 1.0), (2.0, 1.0)))
Related Topics
Django - Makemigrations - No Changes Detected
Python: Give Start and End of Week Data from a Given Date
Possible Values from Sys.Platform
In Python, What Happens When You Import Inside of a Function
How to Save and Restore Multiple Variables in Python
What Is the Official "Preferred" Way to Install Pip and Virtualenv Systemwide
How to Reverse a Dictionary That Has Repeated Values
How to Print a Dictionary Line by Line in Python
Using Only the Db Part of Django
Pandas Latitude-Longitude to Distance Between Successive Rows
How to Obscure a Line Behind a Surface Plot in Matplotlib
Python Memory Usage of Numpy Arrays
Python: Why Does ("Hello" Is "Hello") Evaluate as True