2012-01-25 17 views
4

這裏是一些簡化的代碼,我不明白爲什麼它不起作用。命名元組的Python列表,替換屬性

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)]' 
+2

是你期待什麼輸出? –

+0

-1:完美可怕的標題。不代表一件事。沒有幫助。 –

回答

7

_replace不會做你認爲它做的事情。從docs

somenamedtuple._replace(kwargs)

返回的命名元組新值替換指定字段的新實例:你打電話

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

_replace但你永遠不會存儲它返回的新的Node。它返回一個新對象而不是改變對象'in-place'的原因是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) 
+1

非常感謝。現在有道理,你指出_replace是一個新的對象。 – scriptOmate

+0

@scriptOmate,不客氣。你可以將答案標記爲已解決,如果它確實回答了你的問題:) –

1

記住該列表中的每一項工作像在C用語中指針。 Python變量總是被參考傳遞和使用。也就是說,它的編寫方式,這是真的:

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

我想你想擁有單獨的對象的列表,在這種情況下,你應該將你的Node = MyStruct(...) for循環中。

+0

一般而言,你是對的,但這裏並不重要,因爲所有的對象都是相同的,它們是不可變的。實際上,創建相同(命名)元組的四個實例是浪費。 –