![]() | Ned Batchelder : Blog | Code | Text | Site Python assignment trickiness » Home : Blog : January 2007 |
Python assignment trickinessWednesday 10 January 2007 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 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 This can be helpful with functions returning multiple structured values: def points(): Handy.
tagged:
python» 8 reactions | |
Comments
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.
Add a comment: