Книга: Practical Programming, Fourth Edition
Назад: Storing Data Using Sets
Дальше: Storing Data Using Dictionaries

Storing Data Using Tuples

Tuples are immutable ordered sequences
similar to lists

Lists aren’t the only kind of ordered sequence in Python. You’ve already learned about one of the others: strings (see Chapter 4, ). Formally, a string is an immutable sequence of characters. The characters in a string are ordered, and a string can be indexed and sliced like a list to create new strings:

 >>>​​ ​​rock​​ ​​=​​ ​​'anthracite'
 >>>​​ ​​rock[9]
 'e'
 >>>​​ ​​rock[0:3]
 'ant'
 >>>​​ ​​rock[-5:]
 'acite'
 >>>​​ ​​for​​ ​​character​​ ​​in​​ ​​rock[:5]:
 ...​​ ​​print(character)
 ...
 
 a
 n
 t
 h
 r

Python also has an immutable sequence type called a tuple. Tuples are written using parentheses instead of brackets; like strings and lists, they can be subscripted, sliced, and looped over:

 >>>​​ ​​bases​​ ​​=​​ ​​(​​'A'​​,​​ ​​'C'​​,​​ ​​'G'​​,​​ ​​'T'​​)
 >>>​​ ​​for​​ ​​base​​ ​​in​​ ​​bases:
 ...​​ ​​print(base)
 ...
 A
 C
 G
 T

There’s one small catch: although () represents the empty tuple, a tuple with one element is not written as (x) but as (x,) (with a trailing comma) to avoid ambiguity. If the trailing comma weren’t required, (5 + 3) could mean either 8 (under the rules of arithmetic) or the tuple containing only the value 8:

 >>>​​ ​​(8)
 8
 >>>​​ ​​type((8))
 <class 'int'>
 >>>​​ ​​(8,)
 (8,)
 >>>​​ ​​type((8,))
 <class 'tuple'>
 >>>​​ ​​(5​​ ​​+​​ ​​3)
 8
 >>>​​ ​​(5​​ ​​+​​ ​​3,)
 (8,)

Unlike lists, once a tuple is created, it cannot be mutated:

 >>>​​ ​​life​​ ​​=​​ ​​([​​'Canada'​​,​​ ​​76.5],​​ ​​[​​'United States'​​,​​ ​​75.5],​​ ​​[​​'Mexico'​​,​​ ​​72.0])
 >>>​​ ​​life[0]​​ ​​=​​ ​​life[1]
 Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
  life[0]​​ ​​=​​ ​​life[1]
  ~~~~^^^
 TypeError: 'tuple' object does not support item assignment

However, the objects inside tuples can still be mutated:

 >>>​​ ​​life​​ ​​=​​ ​​([​​'Canada'​​,​​ ​​76.5],​​ ​​[​​'United States'​​,​​ ​​75.5],​​ ​​[​​'Mexico'​​,​​ ​​72.0])
 >>>​​ ​​life[0][1]​​ ​​=​​ ​​80.0
 >>>​​ ​​life
 (['Canada', 80.0], ['United States', 75.5], ['Mexico', 72.0])

Here is an example that explores what is mutable and what isn’t. Let’s build the same tuple as in the previous example, but let’s do it in steps. First, let’s create three lists:

 >>>​​ ​​canada​​ ​​=​​ ​​[​​'Canada'​​,​​ ​​76.5]
 >>>​​ ​​usa​​ ​​=​​ ​​[​​'United States'​​,​​ ​​75.5]
 >>>​​ ​​mexico​​ ​​=​​ ​​[​​'Mexico'​​,​​ ​​72.0]

That builds this memory model:

Mutable

Let’s create a tuple using those variables:

 >>>​​ ​​life​​ ​​=​​ ​​(canada,​​ ​​usa,​​ ​​mexico)
Mutable

Notice that none of the four variables know about the others, and that the tuple object contains three references, one for each of the country lists.

Now, let’s change what variable mexico refers to:

 >>>​​ ​​mexico​​ ​​=​​ ​​[​​'Mexico'​​,​​ ​​72.5]
 >>>​​ ​​life
 (['Canada', 76.5], ['United States', 75.5], ['Mexico', 72.0])

Notice that the tuple that the variable life refers to hasn’t changed. Here’s the new picture.

Mutable

life[0] will always refer to the same list object—we can’t change the memory address stored in life[0]—but we can mutate that list object. And because variable canada also refers to that list, it sees the mutation:

 >>>​​ ​​life[0][1]​​ ​​=​​ ​​80.0
 >>>​​ ​​canada
 ['Canada', 80.0]
Mutable

We hope it is clear how essential it is to thoroughly understand variables and references, as well as how collections contain references to objects, not variables.

Assigning to Multiple Variables Using Tuples

You can assign to multiple variables in the same assignment statement:

 >>>​​ ​​(x,​​ ​​y)​​ ​​=​​ ​​(10,​​ ​​20)
 >>>​​ ​​x
 10
 >>>​​ ​​y
 20

As with a normal assignment statement (see ), Python first evaluates all expressions on the right side of the = symbol, and then it assigns those values to the variables on the left side.

Python uses the comma as a tuple constructor, allowing you to omit the parentheses:

 >>>​​ ​​10,​​ ​​20
 (10, 20)
 >>>​​ ​​x,​​ ​​y​​ ​​=​​ ​​10,​​ ​​20
 >>>​​ ​​x
 10
 >>>​​ ​​y
 20

Multiple assignment also works with lists and sets. Python will happily unpack information from any collection:

 >>>​​ ​​[[w,​​ ​​x],​​ ​​[[y],​​ ​​z]]​​ ​​=​​ ​​[{10,​​ ​​20},​​ ​​[(30,),​​ ​​40]]
 >>>​​ ​​w
 10
 >>>​​ ​​x
 20
 >>>​​ ​​y
 30
 >>>​​ ​​z
 40

Any depth of nesting will work as long as the structure on the right can be translated into the structure on the left.

One of the most common uses of multiple assignment is to swap the values of two variables:

 >>>​​ ​​s1​​ ​​=​​ ​​'first'
 >>>​​ ​​s2​​ ​​=​​ ​​'second'
 >>>​​ ​​s1,​​ ​​s2​​ ​​=​​ ​​s2,​​ ​​s1
 >>>​​ ​​s1
 'second'
 >>>​​ ​​s2
 'first'

The assignment works because the expressions on the RHS are evaluated before being assigned to the variables on the LHS. We will revisit multiple assignments in .

Назад: Storing Data Using Sets
Дальше: Storing Data Using Dictionaries