Wednesday 10 January 2007 — This is almost 18 years old. Be careful.

Here’s a well-known fact about Python assignment: When you have a list (or tuple) on the left-hand side, and a list (or tuple) on the right-hand side, each element on the left is assigned a value from the right, just as if it were in its own assignment statement:

>>> a, b, c = 1, 2, 3

>>> a, b, c

(1, 2, 3)

>>> [a, b, c] = (1, 2, 3)

>>> a

1

>>> b

2

>>> c

3

So far, I don’t think anyone is surprised by this. But notice the recursive nature of the definition. This means that an element on the left can itself be a list (or tuple):

>>> a, (b, c, d), e = 1, (2, 3, 4), 5

>>> c

3

>>> a, _, e = 1, (2, 3, 4), 5

>>> e

5

This can be helpful with functions returning multiple structured values:

def points():

''' Return two pairs of numbers. '''

return (x1, y1), (x2, y2)

# Now I can call points and unpack it flexibly in the same statement:

a, b = points()

(ax, ay), b = points()

_, (bx, by) = points()

(ax, ay), (bx, by) = points()

Handy.

## Comments

Brandon Corfman9:33 AM on 10 Jan 2007def print_point((x,y)):

print x,y

pt = 1,2

print_point(pt)

But every time I start to use it, I think it may be too clever.

Stuart Dootson12:01 PM on 10 Jan 2007Joe W.1:07 PM on 10 Jan 2007Ned Batchelder1:48 PM on 10 Jan 2007Joe: The underscore is not special. It's just another identifier, used in this case because it an unobstrusive name for a variable I'll never use. It's used just like "dummy", or some other name.

DeanG2:44 PM on 11 Jan 2007I'd be cautious of ever assigning a value to '_' when it's the interactive mode's object name for the last returned value.

>>> _

Traceback (most recent call last):

File "", line 1, in ?

NameError: name '_' is not defined

>>> print 5

5

>>> _

Traceback (most recent call last):

File "", line 1, in ?

NameError: name '_' is not defined

>>> 5

5

>>> _

5

>>>

===========

..and I'm glad to see Python uses a back-slash instead of an underscore to wrap an expression to a new line.

Omer Trajman3:33 PM on 11 Jan 2007Patrick Maupin12:58 PM on 17 Jan 2007Assume we have:

x = set([1,2])

y = set([2,3])

And we want to get the element that is the intersection.

You could do something like:

z = x & y

assert len(z) == 1

z = z.pop()

but instead, you can just do:

z, = x & y

This looks a little funny, but it throws an exception if there is not exactly one element in the intersection, and binds z to that element.

Patrick Maupin12:58 PM on 17 Jan 2007Assume we have:

x = set([1,2])

y = set([2,3])

And we want to get the element that is the intersection.

You could do something like:

z = x & y

assert len(z) == 1

z = z.pop()

but instead, you can just do:

z, = x & y

This looks a little funny, but it throws an exception if there is not exactly one element in the intersection, and binds z to that element.

## Add a comment: