# Python assignment trickiness

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)>>> a1>>> b2>>> c3`

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>>> c3>>> a, _, e = 1, (2, 3, 4), 5>>> e5`

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.

Brandon Corfman 9:33 AM on 10 Jan 2007
I experimented once and found it works for function parameters too:
def 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.
So, Python has (some level of) pattern-matching - all the cool (IMO) languages (e.g. Haskell, OCaml, Erlang) do :-)
In "_, (bx, by) = points()", what does the underscore do?
Brandon, thanks, I didn't realize the same trick applied to function parameters, though I think I agree with you that it is too tricky.

Joe: 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.
Joe:
I'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.
Great for use in list comprehension: [func(x) for (x,y) in points()]
Actually, the right-hand side doesn't even need to be a tuple -- it just needs to follow the iterator protocol. This can be very handy.

Assume 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.
Actually, the right-hand side doesn't even need to be a tuple -- it just needs to follow the iterator protocol. This can be very handy.

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