Python Unpacking Operator (*)

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+:

Keyword Arguments: Functions and methods written in Python can now be
called using keyword arguments of the form keyword = value.

Python 1.6+

There's now special syntax that you can use instead of the apply()
function. f(*args, **kwds) is equivalent to apply(f, args, kwds). You
can also use variations f(a1, a2, *args, **kwds) and you can leave one
or the other out: f(*args), f(**kwds).

Python <= 2.7:

Tuple parameter unpacking was removed in Python 3.0.

PEP 3113: Tuple parameter
unpacking removed.
You can no longer write def foo(a, (b, c)): ....
Use def foo(a, b_c): b, c = b_c instead.

Python 3.0+

PEP 3132: Extended Iterable
Unpacking
. You can now write things like a, b, *rest =
some_sequence
. And even *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

Python 3.5+

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).

— https://docs.python.org/3/library/stdtypes.html#old-string-formatting

If you still want to use unpacking *, you can do

names = "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



Leave a reply



Submit