Search code examples
pythonpython-2.7dtonamedtuplepython-attrs

How To Deduce Or Subtype Named Tuple From Another Named Tuple?


Preface

I was wondering how to conceptualize data classes in a pythonic way. Specifically I’m talking about DTO (Data Transfer Object.)

I found a good answer in @jeff-oneill question “Using Python class as a data container” where @joe-kington had a good point to use built-in namedtuple.

Question

In section 8.3.4 of python 2.7 documentation there is good example on how to combine several named tuples. My question is how to achieve the reverse?

Example

Considering the example from documentation:

>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

How can I deduce a “Color” or a “Point” instance from a “Pixel” instance?

Preferably in pythonic spirit.


Solution

  • Here it is. By the way, if you need this operation often, you may create a function for color_ins creation, based on pixel_ins. Or even for any subnamedtuple!

    from collections import namedtuple
    
    Point = namedtuple('Point', 'x y')
    Color = namedtuple('Color', 'red green blue')
    Pixel = namedtuple('Pixel', Point._fields + Color._fields)
    
    pixel_ins = Pixel(x=11, y=22, red=128, green=255, blue=0)
    color_ins = Color._make(getattr(pixel_ins, field) for field in Color._fields)
    
    print color_ins
    

    Output: Color(red=128, green=255, blue=0)

    Function for extracting arbitrary subnamedtuple (without error handling):

    def extract_sub_namedtuple(parent_ins, child_cls):
        return child_cls._make(getattr(parent_ins, field) for field in child_cls._fields)
    
    color_ins = extract_sub_namedtuple(pixel_ins, Color)
    point_ins = extract_sub_namedtuple(pixel_ins, Point)