【问题标题】:Immutable list in PythonPython中的不可变列表
【发布时间】:2014-04-15 22:35:45
【问题描述】:

我正在尝试制作一个在整个应用程序中使用的列表不可变。我认为将这个列表包装在一个元组中就可以了,但似乎tuple(list) 实际上并没有包装,而是复制了列表元素。

>>> a = [1, 2, 3, 4]
>>> b = tuple(a)
>>> b
(1, 2, 3, 4)
>>> a[0] = 2
>>> b # was hoping b[0] to be 2
(1, 2, 3, 4)

是否有一种简单的方法可以在此列表上创建一个不可变的列表支持“视图”(在此视图上进行操作),但反映支持列表发生的任何更改?

我意识到这个问题之前已经被问过,但没有一个回答涉及这种视图支持列表关系(事实上,一些 cmets 甚至建议元组按照我希望的方式工作,但是上面的 sn- p 另有建议)。

【问题讨论】:

  • 所以,基本上,您希望它选择性地可变?这有点难以执行。您实际上想在这里解决什么问题?
  • 为什么要让列表不可变?最好只在文档中声明不应更改列表。如果用户更改它,那是他或她的错。
  • 我真的很好奇这里的用例...听起来很有趣。
  • @PaulBecotte:主要原因是一些重构,我想限制对我以前直接使用的列表成员变量的访问。在内部,我仍然使用列表并对其进行变异,但是每次更改它时,我不一定要被提醒也要更新其外部接口方法(我现在使用@property而不是原来的成员变量)。

标签: python list tuples immutability


【解决方案1】:

如果您不想复制数据,并且想要传递一个不可更改的“列表”,一种方法是创建一个代理对象,一个列表的副本,它禁用所有更改方法,并参考原始列表的阅读方法 - 类似的东西:

class ReadOnlyList(list):
    def __init__(self, other):
        self._list = other

    def __getitem__(self, index):
        return self._list[index]

    def __iter__(self):
        return iter(self._list)

    def __slice__(self, *args, **kw):
        return self._list.__slice__(*args, **kw)

    def __repr__(self):
        return repr(self._list)

    def __len__(self):
        return len(self._list)

    def NotImplemented(self, *args, **kw):
        raise ValueError("Read Only list proxy")

    append = pop = __setitem__ = __setslice__ = __delitem__ = NotImplemented

当然,实现您认为必要的任何其他方法,要么引发错误(或忽略写入指令) - 要么访问内部列表中的相应对象。

【讨论】:

  • 根据我对问题的理解,OP 希望在其他情况下继续更改原始列表。因此,根据定义,它是不可散列的。如果想要一个包含内部列表的时刻快照的哈希,解决方案是创建一个哈希值,该哈希值临时创建一个元组并选择该哈希,并在调用 __hash__ 时返回该值。
  • @eyquem:我刚刚发布了它。并在帖子发布后点击edit,输入示例代码。
  • 谢谢@jsbueno。太糟糕了,没有“一行”-Python 习语或特殊列表作为响应出现,但这确实可以解决问题。再次感谢。
  • @jsbueno:您需要添加到ReadOnlyList 的一种方法是__len__,否则长度始终为0
  • @orange:是​​的,当然。后来我在玩这段代码时注意到了它,但没有在这里更新答案。
猜你喜欢
  • 1970-01-01
  • 2012-06-23
  • 2014-08-09
  • 2020-02-17
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 2015-04-11
  • 1970-01-01
相关资源
最近更新 更多