Chapter 7
Building namedtuples with functional constructors
There are three ways we can build namedtuple instances. The choice of technique we
use is generally based on how much additional information is available at the time of
object construction.
We've shown two of the three techniques in the examples in the previous section.
We'll emphasize the design considerations here. It includes the following choices:
- We can provide the parameter values according to their positions. This works
out well when there are one or more expressions that we were evaluating.
We used it when applying the haversine() function to the start and end
points to create a Leg object.
Leg(start, end, round(haversine(start, end),4)) - We can use the argument notation to assign parameters according to their
positions in a tuple. This works out well when we're getting the arguments
from another iterable or an existing tuple. We used it when using map() to
apply the float() function to the latitude and longitude values.
Point(map(float, pick_lat_lon(*row))) - We can use explicit keyword assignment. While not used in the previous
example, we might see something like this as a way to make the relationships
more obvious:
Point(longitude=float(row[0]), latitude=float(row[1]))
It's helpful to have the flexibility of a variety of ways of created namedtuple
instances. This allows us to more easily transform the structure of data. We
can emphasize features of the data structure that are relevant for reading and
understanding the application. Sometimes, the index number of 0 or 1 is an
important thing to emphasize. Other times, the order of start, end, and
distance is important.
Avoiding stateful classes by using families of tuples
In several previous examples, we've shown the idea of Wrap-Unwrap design
patterns that allow us to work with immutable tuples and namedtuples. The point
of this kind of designs is to use immutable objects that wrap other immutable objects
instead of mutable instance variables.