We can use a NamedTuple subclass named Ranked_XY that contains two attributes: r_x and ranked_y. The ranked_y attribute is an instance of Ranked_Y that has two attributes: r_y and raw. Although this is very easy to build, the resulting objects are annoying to work with because the r_x and r_y values aren't simple peers in a flat structure. We'll introduce a slightly more complex wrapping process that produces a slightly simpler result.
We want the output to be instances of a class defined like this:
class Ranked_XY(NamedTuple): r_x: float r_y: float raw: Pair
We're going to create a flat NamedTuple with multiple peer attributes. This kind of expansion is often easier to work with than deeply nested structures. ...