Using tuples and named tuples
Since Python tuples are immutable objects, they're another excellent example of objects suitable for functional programming. A Python tuple has very few method functions, so almost everything is done using prefix syntax. There are a number of use cases for tuples, particularly when working with list-of-tuple, tuple-of-tuple, and generator-of-tuple constructs.
The namedtuple class adds an essential feature to a tuple: a name that we can use instead of an index. We can exploit named tuples to create objects that are accretions of data. This allows us to write pure functions based on stateless objects, yet keep data bound into tidy object-like packages.
We'll almost always use tuples (and named tuples) in the context of a collection of values. If we're working with single values, or a tidy group of exactly two values, we'll usually use named parameters to a function. When working with collections, however, we may need to have iterable-of-tuples or iterable of the namedtuple class constructs.
The decision to use a tuple or namedtuple object is entirely a matter of convenience. As an example, consider working with a sequence of color values as a three tuple of the form (number, number, number) It's not clear that these are in red, green, blue order. We have a number of approaches for making the tuple structure explicit.
We can clarify the triple structure by creating functions to pick a three-tuple apart, as shown in the following command snippet:
red = lambda color: color[0] green = lambda color: color[1] blue = lambda color: color[2]
Given a tuple, item, we can use red(item) to select the item that has the red component. It can help to provide a more formal type hint on each variable, as follows:
from typing import Tuple, Callable
RGB = Tuple[int, int, int]
red: Callable[[RGB], int] = lambda color: color[0]
This defines a new type, RGB, as a three-tuple. The red variable is provided with a type hint of Callable[[RGB], int] to indicate it should be considered to be a function that accepts an RGB argument and produces an integer result.
Or, we may introduce the following definition using older-style namedtuple class objects:
from collections import namedtuple
Color = namedtuple("Color", ("red", "green", "blue", "name"))
An even better technique is to use the NamedTuple class from the typing module:
from typing import NamedTuple
class Color(NamedTuple):
"""An RGB color."""
red: int
green: int
blue: int
name: str
This definition of the Color class defines a tuple with specific names and type hints for each position within the tuple. This preserves the advantages of performance and immutability. It adds the ability for the mypy program to confirm that the tuple is used properly.
These three technicals allow the use of item.red instead of red(item). Either of these are better than the confusing item[0].
The functional programming application of tuples centers on the iterable-of-tuple design pattern. We'll look closely at a few iterable-of-tuple techniques. We'll look at the namedtuple class techniques in Chapter 7, Additional Tuple Techniques.