如何让我的namedtuple真正不可变?
我创建了一个叫做 SETTINGS 的对象,使用了 namedtuple
,以为里面的列表是不可变的。结果我错了,因为在整个过程中,实际上只是使用了指向原始列表的引用,而这个列表是在一个完全可变的字典里。
所以,当我对我的列表调用 .pop()
时,它也会从我原本以为是不可变的 namedtuple
中删除这个元素。经过一段时间的学习,我现在明白为什么会这样了。
我想知道的是:如何才能创建一个 SETTINGS 的 namedtuple
,让它在最后是完全独立的? 也就是说,只包含数据,不引用其他对象,并且能让用户方便地编辑?我觉得 dict
是人类最容易阅读和编辑的数据结构,所以我才把 dict
拆分成 namedtuple
。
>>> from collections import namedtuple
>>>
>>> _settings = {
... 'ROOM_NAMES': [
... 'Master Bedroom',
... 'Bath',
... 'Kitchen',
... 'Study',
... ],
... }
>>> _Settings = namedtuple('_Settings', [k for k in _settings.keys()])
>>> SETTINGS = _Settings(**_settings)
>>>
>>> names = SETTINGS.ROOM_NAMES
>>> names
['Master Bedroom', 'Bath', 'Kitchen', 'Study']
>>> type(names)
<class 'list'>
>>> # POP 'Study' OFF OF THE LIST
>>> name = names.pop()
>>>
>>> # THIS IS WHAT I EXPECT
>>> name in names
False
>>>
>>> # MISSING HERE AS THIS IS THE END OF THE LINE
>>> name in _settings['ROOM_NAMES']
False
>>>
>>> # MISSING HERE FROM MY NAMEDTUPLE IN THE MIDDLE OF THE LINE
>>> name in SETTINGS.ROOM_NAMES
False
>>>
1 个回答
4
我觉得你对元组是怎么回事有些混淆。即使是“真正的”元组,也并不会让里面的对象变成不可改变的,只有元组本身是不可改变的:
>>> x = [1,2,3]
>>> t = (x,0,3)
>>> t[0].append(4)
>>> t
([1, 2, 3, 4], 0, 3)
我猜你想做的是在开始修改列表之前,先用 .copy()
方法复制一份列表。
>>> a = x.copy()
>>> t = (a,0,1)
>>> t[0].append(5)
>>> t
([1, 2, 3, 4, 5], 0, 1)
>>> x
[1, 2, 3, 4]