A fixed group of values
A tuple is like a list that cannot change after it is created. You make one with commas, usually wrapped in parentheses: ("AAPL", 184.25, 184.5). It suits a small record whose parts have a fixed meaning, such as one quote or one trade. You read it by index like a list, but assigning to a position raises a TypeError. A one-item tuple needs a trailing comma, (5,), because (5) is just the number 5.
quote = ("AAPL", 184.25, 184.5)
# Reading works like a list
print(quote[0], len(quote)) # AAPL 3
# Changing does not
try:
quote[1] = 185.0
except TypeError as error:
print("tuples are fixed:", error)
# One item needs a trailing comma
print(type((5,)), type((5))) # <class 'tuple'> <class 'int'>Unpacking: give the parts names
Unpacking assigns the parts of a tuple (or any sequence) to several names at once: symbol, bid, ask = quote. The number of names must match the number of items, otherwise Python raises a ValueError. Compared with quote[0], quote[1] and quote[2], the names say what each part means, so unpacking is usually clearer than indexing. It also gives the classic swap without a temporary variable: a, b = b, a.
# Unpack a quote into named parts
quote = ("AAPL", 184.25, 184.5)
symbol, bid, ask = quote
print(symbol, round(ask - bid, 2)) # AAPL 0.25
# Swap two values without a temporary
bid, ask = ask, bid
print(bid, ask) # 184.5 184.25
# The count must match
try:
symbol, bid = quote
except ValueError as error:
print("wrong count:", error)Taking the rest with *
Put a * before one name to let it collect everything that is left, as a list: first, *rest = prices or first, *middle, last = prices. Only one starred name is allowed, and the plain names still need an item each. Use _ for a part you do not need, for example first, *_, last = prices.
# * collects what is left, as a list
prices = [184.0, 185.0, 183.2, 186.1]
first, *rest = prices
print(first, rest) # 184.0 [185.0, 183.2, 186.1]
first, *_, last = prices
print(first, last) # 184.0 186.1Unpacking in loops, returns and sorting
Unpacking works anywhere a name is assigned: in a for loop (for symbol, price in quotes), in comprehensions, and on the result of a function that returns several values with return a, b, which really returns one tuple. Tuples also compare item by item, first against first and then, on a tie, second against second, so sorting a list of (price, symbol) tuples orders by price and breaks ties by symbol.
# Return several values, unpack them in the caller
def spread_and_mid(bid, ask):
return ask - bid, (bid + ask) / 2
spread, mid = spread_and_mid(184.25, 184.5)
print(spread, mid) # 0.25 184.375
# Tuples sort by the first item, then the second
quotes = [("AAPL", 184.5), ("MSFT", 410.2), ("GOOG", 171.0)]
by_price = sorted((price, symbol) for symbol, price in quotes)
print(by_price) # [(171.0, 'GOOG'), (184.5, 'AAPL'), (410.2, 'MSFT')]
for price, symbol in by_price:
print(symbol, price)(symbol, bid, ask). Use a list when you have many similar items and may add or remove some. Because a tuple cannot change, it can also be used where a list cannot, for example as a key in a dictionary, which is coming soon.(a, b, c): a fixed group; read it, but do not change it.x, y = pair: unpack into names; the counts must match.first, *rest = items: the starred name collects the rest as a list.
Next up: dictionaries, which look values up by a name instead of a position.
Lab · what's graded
- Unpack a quote with
quote_stats25 pts - Take both ends with
first_last25 pts - Rank quotes by price with
ranked25 pts - Find the cheapest venue with
best_ask25 pts