4

这是一些简化的代码,我不明白为什么它不起作用。

from collections import namedtuple

MyStruct = namedtuple('MyStruct', 'ThreadInstance ThreadName Mnemonic IpAddr IpGW Status Mode')

Node = MyStruct(None, '', '', '', '',  -1, 0)
NodeDb = []
for id in range(4):
    NodeDb.append(Node)

NodeDb[2]._replace(ThreadName='T2')
NodeDb[2]._replace(Mnemonic='ABCD')
NodeDb[2]._replace(IpAddr='192.0.1.2')
NodeDb[2]._replace(IpGW='192.0.1.3')
NodeDb[2]._replace(Status=0)
NodeDb[2]._replace(Mode=2)

print(NodeDb)

这是输出

'>>>
[MyStruct(ThreadInstance=None, ThreadName='', Mnemonic='', IpAddr='', IpGW='', Status=-1, Mode=0),
 MyStruct(ThreadInstance=None, ThreadName='', Mnemonic='', IpAddr='', IpGW='', Status=-1, Mode=0), 
 MyStruct(ThreadInstance=None, ThreadName='', Mnemonic='', IpAddr='', IpGW='', Status=-1, Mode=0), 
 MyStruct(ThreadInstance=None, ThreadName='', Mnemonic='', IpAddr='', IpGW='', Status=-1, Mode=0)]'
4

2 回答 2

7

_replace不做你认为它做的事。从文档

somenamedtuple._replace(kwargs)

返回命名元组的新实例,用新值替换指定字段:

>>> p = Point(x=11, y=22)  
>>> p._replace(x=33)  
Point(x=33, y=22)

您正在调用_replace,但您从不存储Node它返回的新值。它返回一个新对象而不是“就地”更改对象的原因namedtuples是根据定义,它们是不可变的,即它们在您创建它们之后无法更改。

请注意,您的for循环会创建一个列表,其中包含对相同的四个引用Node。在这种情况下,这并不是真正的问题,因为您正在创建的对象都是相同的并且namedtuple是不可变的,但通常要注意这一点。

总而言之:

from collections import namedtuple

MyStruct = namedtuple('MyStruct', 'ThreadInstance ThreadName Mnemonic IpAddr IpGW Status Mode')

NodeDb = []
Node = MyStruct(None, '', '', '', '',  -1, 0)
for id in range(4):
    NodeDb.append(Node)

NodeDb[2] = NodeDb[2]._replace(ThreadName='T2',
                               Mnemonic='ABCD',
                               IpAddr='192.0.1.2',
                               IpGW='192.0.1.3',
                               Status=0,
                               Mode=2)

print(NodeDb)
于 2012-01-25T20:29:23.353 回答
1

请记住,该列表中的每个项目都像C 语言中的指针一样工作。Python 变量总是通过引用传递和使用。也就是说,按照它的写法,这是真的:

assert NodeDb[0] is NodeDb[1] is NodeDb[2] is NodeDb[3] # True

我认为你想要一个单独的对象列表,在这种情况下,你应该Node = MyStruct(...)在你的 for 循环中移动。

于 2012-01-25T20:22:32.767 回答