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
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.
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.
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.
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.
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.
Add a comment: