Tuples and sets

Two more structures. Each does one job that lists and dicts do badly.

Tuples: values that belong together

A tuple is a fixed group of values, written with parentheses. Use it when a few values form one thing, like an item and its price, or a position as (row, column).

pair = ("bread", 25)
print(pair[0])
print(pair[1])
print(len(pair))

Indexing and slicing work as for lists, but a tuple cannot be changed: no append, no assigning to a position. That is the point. A tuple says "these go together and this is the complete set".

The parentheses are optional when writing a tuple; it is the commas that make it one. pair = "bread", 25 means the same thing. And tuple(...) turns a list into a tuple, just as list(...) turns a tuple into a list.

Unpacking

A tuple's values can be pulled out into separate names in one line.

pair = ("bread", 25)
item, price = pair
print(item)
print(price)

This is also how a function returns two things, and it gives a one-line swap, which you may remember doing with a temporary name in the Names exercises. (min and max below pick the smallest and largest of a list; the next page covers them properly.)

def cheapest_and_dearest(prices):
    return min(prices), max(prices)

low, high = cheapest_and_dearest([40, 25, 2.5])
print(low, high)

a, b = "apple", "bread"
a, b = b, a
print(a, b)

Sets: no duplicates, fast membership

A set holds values with no order and no repeats. Build one with curly braces, or from a list with set().

basket = ["apple", "bread", "apple", "milk", "apple"]
unique = set(basket)
print(unique)
print(len(unique))

Because a set has no order, the order it prints in can differ from the order you added things, and even from one run to the next. Adding a value already present does nothing. Sets are the natural answer to "have I seen this before?".

seen = set()
seen.add("apple")
seen.add("bread")
seen.add("apple")
print(seen)
print("apple" in seen)
print("milk" in seen)

Sets have no positions, so seen[0] is an error. To get an empty set write set(); {} is an empty dictionary.

Combining sets

shop_a = {"apple", "bread", "milk"}
shop_b = {"bread", "milk", "eggs"}
print(shop_a & shop_b)
print(shop_a | shop_b)
print(shop_a - shop_b)

& is what both have, | is everything in either, - is what the first has that the second does not.

Which structure?

You need Use
An ordered collection you will add to and change list
A few values that form one thing, never changed tuple
Lookup by a key you choose dict
Uniqueness or fast "is it in there?" set

Try it

Split a pair

Each stock entry is a tuple (item, quantity). Write describe(entry) that returns the text <quantity> x <item>.

describe(("bread", 3))  ->  "3 x bread"
def describe(entry):
    ...

Unique items

Write unique_count(basket) that returns how many different items are in the list basket.

unique_count(["apple", "bread", "apple", "milk", "apple"])  ->  3
unique_count([])                                           ->  0
def unique_count(basket):
    ...

In both shops

Two shops each have a list of items. Write in_both(a, b) that returns a list of the items that appear in both, each item once, in any order.

in_both(["apple", "bread", "milk"], ["milk", "eggs", "apple"])  ->  ["apple", "milk"]   (or ["milk", "apple"])
in_both(["apple"], ["bread"])                                   ->  []
def in_both(a, b):
    ...

Next: Built-in functions.