如何为命名元组添加字段?

26 投票
4 回答
37884 浏览
提问于 2025-04-17 18:35

我正在使用一个包含命名元组的列表。我想在命名元组创建后,给每个命名元组添加一个字段。看起来我可以通过把它当作一个属性来做到这一点(就像这样 namedtuple.attribute = 'foo'),但是这样的话,它就不会被添加到字段列表中。如果我不打算用字段列表,有没有什么理由我不应该这样做?有没有更好的方法来添加一个字段?

>>> 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')

4 个回答

5

你可以很简单地把命名元组连接在一起,但要记住它们是不可改变的。

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)
13

注意,这里你是在修改命名元组的type,而不是这个类型的实例。在这种情况下,你可能想要从旧的类型创建一个新的类型,并添加一个额外的字段:

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

例如:

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

你所做的事情之所以有效,是因为 namedtuple(...) 返回了一个新类。要真正得到一个结果对象,你需要实例化这个类。所以正确的做法是:

Result = namedtuple('Result', ['x', 'y'])
result = Result(5, 6)

你会发现给这些对象添加属性是不行的。所以你不应该这样做的原因就是因为它根本不行。只有滥用类对象才有效,我希望我不需要详细解释为什么这是个非常糟糕的主意。

请注意,无论你是否能给命名元组添加属性(即使你提前列出了所有需要的属性),一旦创建了命名元组对象,你是无法更改它的。元组是不可变的。所以如果你需要在创建后以任何方式或形式更改对象,你就不能使用 namedtuple。你最好定义一个自定义类(因为 namedtuple 为你添加的一些东西对于可变对象来说根本没有意义)。

撰写回答