ruk·si

🐍 Python
Tuples

Updated at 2018-06-09 14:24

Tuples are immutable sequences of data. You use both tuples and named tuples to enforce a better structure for your data that is not complex enough to create a class for it.

from typing import Tuple

my_tuple: Tuple[int, int, int] = (1, 2, 3)
my_tuple[0] = 3 # => TypeError: 'tuple' object does not support item assignment

Non-empty tuples are always truthy in Python.

assert bool(()) is False
assert bool((0,)) is True
assert bool((False,)) is True
assert bool((None,)) is True
assert bool((0, None, False)) is True

Tuples unpack without much effort. Even with nested tuples.

from typing import List, Tuple

cities: List[Tuple[str, Tuple[float, float]]] = [
    ('Tokyo', (35.68, 139.69)),
    ('Mexico City', (19.43, -99.13)),
]

for city, (latitude, longitude) in cities:
    assert type(city) == str
    assert type(latitude) == float
    assert type(longitude) == float

# creates tuples by default if you leave out the parentheses
a, b, c = (1, 2, 3)
d, e, f = 4, 5, 6

Named tuples are "memory-efficient classes". The underlying implementation is a Python class so you can inherit from them or even add methods to them with inheritance.

from collections import namedtuple

Car = namedtuple('Car', ['color', 'mileage'])
assert Car._fields == ('color', 'mileage')

my_car = Car(color='blue', mileage=99)
assert my_car.color == my_car[0] == 'blue'
assert my_car.mileage == my_car[1] == 99

class SportsCar(Car):

    def engine_sound(self) -> str:
        return f'{self.__class__.__name__}: VROOM'

my_sports_car = SportsCar('red', 1000)
assert my_sports_car.color == my_sports_car[0] == 'red'
assert my_sports_car.mileage == my_sports_car[1] == 1000
assert my_sports_car.engine_sound() == 'SportsCar: VROOM'

Tuples and named tuples are both immutable. Write once, read many times. But you can duplicate and modify tuples.

from collections import namedtuple

Car = namedtuple('Car', ['color', 'mileage'])
c1 = Car(color='red', mileage=100)
c2 = c1._replace(color='purple')

assert c1.color == 'red' and c1.mileage == 100
assert c2.color == 'purple' and c2.mileage == 100

You can also use the NamedTuple class.

from typing import NamedTuple

class Car(NamedTuple):
    color: str
    mileage: float
    automatic: bool

car1 = Car(color='red', mileage=123.45, automatic=True)
assert car1.mileage == 123.45
# car1.mileage = 1.15 # => AttributeError: can't set attribute
# car1.status = 'broken' # => AttributeError: 'Car' object has no...

Source

  • Python Tricks The Book, Dan Bader
  • Fluent Python, Luciano Ramalho