how do I add fields to a namedtuple?

30,290

Solution 1

Notice that here you're modifying the type of the named tuples, not instances of that type. In this case, you'd probably want to create a new type with an additional field from the old one:

result = namedtuple('Result',result._fields+('point',))

e.g.:

>>> result = namedtuple('Result',['x','y'])
>>> result = namedtuple('Result',result._fields+('point',))
>>> result._fields
('x', 'y', 'point')

Solution 2

You can easily concatenate namedtuples, keeping in mind that they are immutable

from collections import namedtuple

T1 = namedtuple('T1', 'a,b')
T2 = namedtuple('T2', 'c,d')

t1 = T1(1,2)
t2 = T2(3,4)

def sum_nt_classes(*args):
    return namedtuple('_', ' '.join(sum(map(lambda t:t._fields, args), ())))

def sum_nt_instances(*args):
    return sum_nt_classes(*args)(*sum(args,()))

print sum_nt_classes(T1,T2)(5,6,7,8)
print sum_nt_instances(t1,t2)

Solution 3

You cannot add a new field to a namedtuple after defining it. Only way is to create a new template and creating new namedtuple instances.

Analysis

>>> from collections import namedtuple
>>> result = namedtuple('Result',['x','y'])
>>> result
<class '__main__.Result'>

result is not a tuple, but the class which creates tuples.

>>> result.x
<property object at 0x02B942A0>

You create a new tuple like this:

>>> p = result(1, 2)
>>> p
Result(x=1, y=2)

>>> p.x
1

Prints the value x in p.

>>> p.x = 5

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    p.x = 5
AttributeError: can't set attribute

This throws error because tuple is immutable.

>>> result.x = 5
>>> result
<class '__main__.Result'>
>>> result._fields
('x', 'y')
>>> p = result(1, 2)
>>> p
Result(x=1, y=2)

This doesn't change anything.

>>> result.description = 'point'
>>> result
<class '__main__.Result'>
>>> result._fields
('x', 'y')

This doesn't change anything either.

Solution

>>> result = namedtuple('Result', ['x','y'])
>>> p = result(1, 2)
>>> p
Result(x=1, y=2)
>>> # I need one more field
>>> result = namedtuple('Result',['x','y','z'])
>>> p1 = result(1, 2, 3)
>>> p1
Result(x=1, y=2, z=3)
>>> p
Result(x=1, y=2)
Share:
30,290
rudivonstaden
Author by

rudivonstaden

Updated on July 17, 2022

Comments

  • rudivonstaden
    rudivonstaden almost 2 years

    I am working with a list of namedtuples. I would like to add a field to each named tuple after it has already been created. It seems I can do that by just referencing it as an attribute (as in namedtuple.attribute = 'foo'), but then it isn't added to the list of fields. Is there any reason why I shouldn't do it this way if I don't do anything with the fields list? Is there a better way to add a field?

    >>> from collections import namedtuple
    >>> result = namedtuple('Result',['x','y'])
    >>> result.x = 5
    >>> result.y = 6
    >>> (result.x, result.y)
    (5, 6)
    >>> result.description = 'point'
    >>> (result.x, result.y, result.description)
    (5, 6, 'point')
    >>> result._fields
    ('x', 'y')