← 学习库 Think Python 2e 目录

Chapter 13

> 来源: Think Python 2e (Allen B. Downey)

> 原页: https://greenteapress.com/thinkpython/html/thinkpython013.html

\

[插图缺失:thinkpython012.html]
[ [](thinkpython014.html)

------------------------------------------------------------------------

Chapter 12   Tuples

12.1   Tuples are immutable

A tuple is a sequence of values. The values can be any type, and they are indexed by integers, so in that respect tuples are a lot like lists. The important difference is that tuples are immutable.

Syntactically, a tuple is a comma-separated list of values:

>>> t = 'a', 'b', 'c', 'd', 'e'

Although it is not necessary, it is common to enclose tuples in parentheses:

>>> t = ('a', 'b', 'c', 'd', 'e')

To create a tuple with a single element, you have to include a final comma:

>>> t1 = 'a',

>>> type(t1)

<type 'tuple'>

A value in parentheses is not a tuple:

>>> t2 = ('a')

>>> type(t2)

<type 'str'>

Another way to create a tuple is the built-in function tuple. With no argument, it creates an empty tuple:

tuple0010

If the argument is a sequence (string, list or tuple), the result is a tuple with the elements of the sequence:

tuple0011

Because tuple is the name of a built-in function, you should avoid using it as a variable name.

Most list operators also work on tuples. The bracket operator indexes an element:

tuple0013

And the slice operator selects a range of elements.

tuple0014

But if you try to modify one of the elements of the tuple, you get an error:

tuple0015

You can’t modify the elements of a tuple, but you can replace one tuple with another:

tuple0016

12.2   Tuple assignment

It is often useful to swap the values of two variables. With conventional assignments, you have to use a temporary variable. For example, to swap a and a:

tuple0019

This solution is cumbersome; tuple assignment is more elegant:

tuple0020

The left side is a tuple of variables; the right side is a tuple of expressions. Each value is assigned to its respective variable. All the expressions on the right side are evaluated before any of the assignments.

The number of variables on the left and the number of values on the right have to be the same:

tuple0021

More generally, the right side can be any kind of sequence (string, list or tuple). For example, to split an email address into a user name and a domain, you could write:

tuple0022

The return value from tuple is a list with two elements; the first element is assigned to tuple, the second to tuple0.

tuple0026

12.3   Tuples as return values

Strictly speaking, a function can only return one value, but if the value is a tuple, the effect is the same as returning multiple values. For example, if you want to divide two integers and compute the quotient and remainder, it is inefficient to compute a00 and then a00. It is better to compute them both at the same time.

The built-in function tuple0 takes two arguments and returns a tuple of two values, the quotient and remainder. You can store the result as a tuple:

tuple0030

Or use tuple assignment to store the elements separately:

tuple0031

Here is an example of a function that returns a tuple:

tuple0032

a00 and a00 are built-in functions that find the largest and smallest elements of a sequence. tuple00 computes both and returns a tuple of two values.

12.4   Variable-length argument tuples

Functions can take a variable number of arguments. A parameter name that begins with a gathers arguments into a tuple. For example, tuple003 takes any number of arguments and prints them:

tuple0038

The gather parameter can have any name you like, but a000 is conventional. Here’s how the function works:

tuple0040

The complement of gather is scatter. If you have a sequence of values and you want to pass it to a function as multiple arguments, you can use the a operator. For example, tuple0 takes exactly two arguments; it doesn’t work with a tuple:

tuple0043

But if you scatter the tuple, it works:

tuple0044

Exercise 1  

Many of the built-in functions use variable-length argument tuples. For example, a00 and a00 can take any number of arguments:

tuple0047

But a00 does not.

tuple0049

Write a function called tuple0 that takes any number of arguments and returns their sum.

12.5   Lists and tuples

a00 is a built-in function that takes two or more sequences and “zips” them into a list of tuples where each tuple contains one element from each sequence. In Python 3, a00 returns an iterator of tuples, but for most purposes, an iterator behaves like a list.

This example zips a string and a list:

tuple0053

The result is a list of tuples where each tuple contains a character from the string and the corresponding element from the list.

If the sequences are not the same length, the result has the length of the shorter one.

tuple0054

You can use tuple assignment in a a00 loop to traverse a list of tuples:

tuple0056

Each time through the loop, Python selects the next tuple in the list and assigns the elements to tuple0 and tuple0. The output of this loop is:

tuple0059

If you combine a00, a00 and tuple assignment, you get a useful idiom for traversing two (or more) sequences at the same time. For example, tuple0062 takes two sequences, a0 and a0, and returns a000 if there is an index a such that tuple0067:

tuple0068

If you need to traverse the elements of a sequence and their indices, you can use the built-in function tuple0069:

tuple0070

The output of this loop is:

tuple0071

Again.

12.6   Dictionaries and tuples

Dictionaries have a method called tuple that returns a list of tuples, where each tuple is a key-value pair.

tuple0073

As you should expect from a dictionary, the items are in no particular order. In Python 3, tuple returns an iterator, but for many purposes, iterators behave like lists.

Going in the other direction, you can use a list of tuples to initialize a new dictionary:

tuple0075

Combining a000 with a00 yields a concise way to create a dictionary:

tuple0078

The dictionary method tuple0 also takes a list of tuples and adds them, as key-value pairs, to an existing dictionary.

Combining tuple, tuple assignment and a00, you get the idiom for traversing the keys and values of a dictionary:

tuple0082

The output of this loop is:

tuple0083

Again.

It is common to use tuples as keys in dictionaries (primarily because you can’t use lists). For example, a telephone directory might map from last-name, first-name pairs to telephone numbers. Assuming that we have defined a000, tuple and tuple0, we could write:

tuple0087

The expression in brackets is a tuple. We could use tuple assignment to traverse this dictionary.

tuple0088

This loop traverses the keys in tuple0089, which are tuples. It assigns the elements of each tuple to a000 and tuple, then prints the name and corresponding telephone number.

There are two ways to represent tuples in a state diagram. The more detailed version shows the indices and elements just as they appear in a list. For example, the tuple tuple0092 would appear as in Figure 12.1.


[插图缺失:thinkpython020.png]

Figure 12.1: State diagram.


But in a larger diagram you might want to leave out the details. For example, a diagram of the telephone directory might appear as in Figure 12.2.


[插图缺失:thinkpython021.png]

Figure 12.2: State diagram.


Here the tuples are shown using Python syntax as a graphical shorthand.

The telephone number in the diagram is the complaints line for the BBC, so please don’t call it.

12.7   Comparing tuples

The relational operators work with tuples and other sequences; Python starts by comparing the first element from each sequence. If they are equal, it goes on to the next elements, and so on, until it finds elements that differ. Subsequent elements are not considered (even if they are really big).

tuple0093

The a000 function works the same way. It sorts primarily by first element, but in the case of a tie, it sorts by second element, and so on.

This feature lends itself to a pattern called DSU for

Decorate

a sequence by building a list of tuples with one or more sort keys preceding the elements from the sequence,

Sort

the list of tuples, and

Undecorate

by extracting the sorted elements of the sequence.

For example, suppose you have a list of words and you want to sort them from longest to shortest:

tuple0095

The first loop builds a list of tuples, where each tuple is a word preceded by its length.

a000 compares the first element, length, first, and only considers the second element to break ties. The keyword argument tuple0097 tells a000 to go in decreasing order.

The second loop traverses the list of tuples and builds a list of words in descending order of length.

Exercise 2  

In this example, ties are broken by comparing words, so words with the same length appear in reverse alphabetical order. For other applications you might want to break ties at random. Modify this example so that words with the same length appear in random order. Hint: see the tuple0 function in the tuple0 module. Solution: tuple0101.

12.8   Sequences of sequences

I have focused on lists of tuples, but almost all of the examples in this chapter also work with lists of lists, tuples of tuples, and tuples of lists. To avoid enumerating the possible combinations, it is sometimes easier to talk about sequences of sequences.

In many contexts, the different kinds of sequences (strings, lists and tuples) can be used interchangeably. So how and why do you choose one over the others?

To start with the obvious, strings are more limited than other sequences because the elements have to be characters. They are also immutable. If you need the ability to change the characters in a string (as opposed to creating a new string), you might want to use a list of characters instead.

Lists are more common than tuples, mostly because they are mutable. But there are a few cases where you might prefer tuples:

  1. In some contexts, like a tuple0 statement, it is syntactically simpler to create a tuple than a list. In other contexts, you might prefer a list.
  2. If you want to use a sequence as a dictionary key, you have to use an immutable type like a tuple or string.
  3. If you are passing a sequence as an argument to a function, using tuples reduces the potential for unexpected behavior due to aliasing.

Because tuples are immutable, they don’t provide methods like a000 and tuple01, which modify existing lists. But Python provides the built-in functions tuple0 and tuple010, which take any sequence as a parameter and return a new list with the same elements in a different order.

12.9   Debugging

Lists, dictionaries and tuples are known generically as data structures; in this chapter we are starting to see compound data structures, like lists of tuples, and dictionaries that contain tuples as keys and lists as values. Compound data structures are useful, but they are prone to what I call shape errors; that is, errors caused when a data structure has the wrong type, size or composition. For example, if you are expecting a list with one integer and I give you a plain old integer (not in a list), it won’t work.

To help debug these kinds of errors, I have written a module called tuple0107 that provides a function, also called tuple0108, that takes any kind of data structure as an argument and returns a string that summarizes its shape. You can download it from tuple0109

Here’s the result for a simple list:

tuple0110

A fancier program might write “list of 3 ints,” but it was easier not to deal with plurals. Here’s a list of lists:

tuple0111

If the elements of the list are not the same type, tuple0112 groups them, in order, by type:

tuple0113

Here’s a list of tuples:

tuple0114

And here’s a dictionary with 3 items that map integers to strings.

tuple0115

If you are having trouble keeping track of your data structures, tuple0116 can help.

12.10   Glossary

tuple:

An immutable sequence of elements.

tuple assignment:

An assignment with a sequence on the right side and a tuple of variables on the left. The right side is evaluated and then its elements are assigned to the variables on the left.

gather:

The operation of assembling a variable-length argument tuple.

scatter:

The operation of treating a sequence as a list of arguments.

DSU:

Abbreviation of “decorate-sort-undecorate,” a pattern that involves building a list of tuples, sorting, and extracting part of the result.

data structure:

A collection of related values, often organized in lists, dictionaries, tuples, etc.

shape (of a data structure):

A summary of the type, size and composition of a data structure.

12.11   Exercises

Exercise 3  

Write a function called tuple0117 that takes a string and prints the letters in decreasing order of frequency. Find text samples from several different languages and see how letter frequency varies between languages. Compare your results with the tables at tuple0118. Solution: tuple0119.

Exercise 4  

More anagrams!

  1. Write a program that reads a word list from a file (see Section 9.1) and prints all the sets of words that are anagrams.

    Here is an example of what the output might look like:

    tuple0120

    Hint: you might want to build a dictionary that maps from a set of letters to a list of words that can be spelled with those letters. The question is, how can you represent the set of letters in a way that can be used as a key?

  2. Modify the previous program so that it prints the largest set of anagrams first, followed by the second largest set, and so on.
  3. In Scrabble a “bingo” is when you play all seven tiles in your rack, along with a letter on the board, to form an eight-letter word. What set of 8 letters forms the most possible bingos? Hint: there are seven.

    Solution: tuple0121.

Exercise 5  

Two words form a “metathesis pair” if you can transform one into the other by swapping two letters; for example, “converse” and “conserve.” Write a program that finds all of the metathesis pairs in the dictionary. Hint: don’t test all pairs of words, and don’t test all possible swaps. Solution: tuple0122. Credit: This exercise is inspired by an example at tuple0123.

Exercise 6  

Here’s another Car Talk Puzzler (tuple0124):

What is the longest English word, that remains a valid English word, as you remove its letters one at a time?

Now, letters can be removed from either end, or the middle, but you can’t rearrange any of the letters. Every time you drop a letter, you wind up with another English word. If you do that, you’re eventually going to wind up with one letter and that too is going to be an English word—one that’s found in the dictionary. I want to know what’s the longest word and how many letters does it have?

I’m going to give you a little modest example: Sprite. Ok? You start off with sprite, you take a letter off, one from the interior of the word, take the r away, and we’re left with the word spite, then we take the e off the end, we’re left with spit, we take the s off, we’re left with pit, it, and I.

Write a program to find all words that can be reduced in this way, and then find the longest one.

This exercise is a little more challenging than most, so here are some suggestions:

  1. You might want to write a function that takes a word and computes a list of all the words that can be formed by removing one letter. These are the “children” of the word.
  2. Recursively, a word is reducible if any of its children are reducible. As a base case, you can consider the empty string reducible.
  3. The wordlist I provided, tuple0125, doesn’t contain single letter words. So you might want to add “I”, “a”, and the empty string.
  4. To improve the performance of your program, you might want to memoize the words that are known to be reducible.

Solution: tuple0126.

Contribute

If you would like to make a contribution to support my books, you can use the button below. Thank you!

Pay what you want:

Small $1.00 USD Medium $5.00 USD Large $10.00 USD X-Large $20.00 USD XX-Large $50.00 USD

Are you using one of our books in a class?

We'd like to know about it. Please consider filling out this short survey.


------------------------------------------------------------------------

\

[插图缺失:thinkpython012.html]
[ [](thinkpython014.html)

---

← Chapter 12Chapter 14 →