Learning Python - Mark Lutz [168]
>>> nudge = 1
>>> wink = 2
>>> nudge, wink = wink, nudge # Tuples: swaps values
>>> nudge, wink # Like T = nudge; nudge = wink; wink = T
(2, 1)
In fact, the original tuple and list assignment forms in Python have been generalized to accept any type of sequence on the right as long as it is of the same length as the sequence on the left. You can assign a tuple of values to a list of variables, a string of characters to a tuple of variables, and so on. In all cases, Python assigns items in the sequence on the right to variables in the sequence on the left by position, from left to right:
>>> [a, b, c] = (1, 2, 3) # Assign tuple of values to list of names
>>> a, c
(1, 3)
>>> (a, b, c) = "ABC" # Assign string of characters to tuple
>>> a, c
('A', 'C')
Technically speaking, sequence assignment actually supports any iterable object on the right, not just any sequence. This is a more general concept that we will explore in Chapters 14 and 20.
Advanced sequence assignment patterns
Although we can mix and match sequence types around the = symbol, we must have the same number of items on the right as we have variables on the left, or we’ll get an error. Python 3.0 allows us to be more general with extended unpacking syntax, described in the next section. But normally, and always in Python 2.X, the number of items in the assignment target and subject must match:
>>> string = 'SPAM'
>>> a, b, c, d = string # Same number on both sides
>>> a, d
('S', 'M')
>>> a, b, c = string # Error if not
...error text omitted...
ValueError: too many values to unpack
To be more general, we can slice. There are a variety of ways to employ slicing to make this last case work:
>>> a, b, c = string[0], string[1], string[2:] # Index and slice
>>> a, b, c
('S', 'P', 'AM')
>>> a, b, c = list(string[:2]) + [string[2:]] # Slice and concatenate
>>> a, b, c
('S', 'P', 'AM')
>>> a, b = string[:2] # Same, but simpler
>>> c = string[2:]
>>> a, b, c
('S', 'P', 'AM')
>>> (a, b), c = string[:2], string[2:] # Nested sequences
>>> a, b, c
('S', 'P', 'AM')
As the last example in this interaction demonstrates, we can even assign nested sequences, and Python unpacks their parts according to their shape, as expected. In this case, we are assigning a tuple of two items, where the first item is a nested sequence (a string), exactly as though we had coded it this way:
>>> ((a, b), c) = ('SP', 'AM') # Paired by shape and position
>>> a, b, c
('S', 'P', 'AM')
Python pairs the first string on the right ('SP') with the first tuple on the left ((a, b)) and assigns one character at a time, before assigning the entire second string ('AM') to the variable c all at once. In this event, the sequence-nesting shape of the object on the left must match that of the object on the right. Nested sequence assignment like this is somewhat advanced, and rare to see, but it can be convenient for picking out the parts of data structures with known shapes.
For example, we’ll see in Chapter 13 that this technique also works in for loops, because loop items are assigned to the target given in the loop header:
for (a, b, c) in [(1, 2, 3), (4, 5, 6)]: ... # Simple tuple assignment
for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]: ... # Nested tuple assignment
In a note in Chapter 18, we’ll also see that this nested tuple (really, sequence) unpacking assignment form works for function argument lists in Python 2.6 (though not in 3.0), because function arguments are passed by assignment as well:
def f(((a, b), c)): # For arguments too in Python 2.6, but not 3.0
f(((1, 2), 3))
Sequence-unpacking assignments also give rise to another common coding idiom in Python—assigning an integer series to a set of variables:
>>> red, green, blue = range(3)
>>> red, blue
(0, 2)
This initializes the three names to the integer codes 0, 1, and 2, respectively (it’s Python’s equivalent of the enumerated data types you may have seen in other languages). To make