24

我正在使用一个命名元组列表。我想在创建每个命名元组后为其添加一个字段。看来我可以通过仅将其作为属性(如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

4 回答 4

21

你所做的工作因为namedtuple(...)返回一个新的类。要实际获取 Result 对象,您需要实例化该类。所以正确的做法是:

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

你会发现给这些对象添加属性是行不通的。所以你不应该这样做的原因是因为它不起作用。只有滥用类对象才有效,我希望我不需要详细说明为什么这是一个可怕的、可怕的想法。

请注意,无论您是否可以向 namedtuple 添加属性(即使您事先列出了所有需要的属性),您都无法在创建 namedtuple 对象后对其进行更改。元组是不可变的。因此,如果您需要在创建后出于任何原因以任何方式或形状更改对象,则不能使用namedtuple. 你最好定义一个自定义类(namedtuple为你添加的一些东西甚至对可变对象没有意义)。

于 2013-03-10T16:43:43.743 回答
13

请注意,这里您正在修改type命名元组的 ,而不是该类型的实例。在这种情况下,您可能希望使用旧类型的附加字段创建一个新类型:

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

例如:

>>> result = namedtuple('Result',['x','y'])
>>> result = namedtuple('Result',result._fields+('point',))
>>> result._fields
('x', 'y', 'point')
于 2013-03-10T16:43:52.170 回答
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)
于 2018-02-26T21:22:14.237 回答
4

namedtuple定义后不能向 a 添加新字段。唯一的方法是创建一个新模板并创建新namedtuple实例。

分析

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

result不是元组,而是创建元组的类。

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

你创建一个像这样的新元组:

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

>>> p.x
1

打印 中的值xp

>>> p.x = 5

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

这会引发错误,因为元组是不可变的。

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

这不会改变任何事情。

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

这也不会改变任何事情。

解决方案

>>> 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)
于 2013-03-10T16:39:02.780 回答