Python syntax for namedtuple inside a namedtuple

Question:

Is it possible to have a namedtuple inside another namedtuple?

For example:

from collections import namedtuple

Position = namedtuple('Position', 'x y')
Token = namedtuple('Token', ['key', 'value', Position])

which gives a “ValueError: Type names and field names must be valid identifiers”

Also, I am curious if there is a more Pythonic approach to build such a nested container?

Asked By: Yannis

||

Answers:

You are mixing up two concepts – structure of namedtuple, and values assigned to them. Structure requires list of unique names. Values may be anything, including another namedtuple.

from collections import namedtuple

Position = namedtuple('Position', 'x y')
Token = namedtuple('Token', ['key', 'value', 'position'])

t = Token('ABC', 'DEF', Position(1, 2))
assert t.position.x == 1
Answered By: Ɓukasz Rogalski

Here a general function to transform a nested dictionary to a nested namedtuple

from collections import namedtuple

def dict2namedtuple(name, d):
    values, keys = [], []
    for k in d:
        keys.append(k)

        v = d[k]
        if isinstance(v, dict):
            values.append(dict2namedtuple(k, v))
        else:
            values.append(v)

    T = namedtuple(name, keys)
    return T(*values)


def namedtuple2dict(nt):
    d = {}
    for k in nt._fields:
        v = getattr(nt, k)
        try:
            d[k] = namedtuple2dict(v)
        except AttributeError:
            d[k] = v
    return d


test_dict = {'a': 1, 'b': 2, 'c': {'d': 3, 'e': 4}}
nt = dict2namedtuple('test', d=test_dict)
dc = namedtuple2dict(nt)
assert dc == test_dict
print('namedtuple', nt)
print('dict', dc)

EDIT:
I added a function for the inverse problem namedtuple2dict. In my experience namedtuple._asidct() works fine, but @Chev_603 mentioned some problems.

Answered By: scleronomic
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.