具有固定和有序键的可变字典

时间:2014-07-15 16:29:00

标签: python dictionary

我使用OrderedDict存储一些重要数据。我想确保,意外插入此词典的新密钥会引发异常,但我希望dict为 mutable 。我希望修复密钥(在__init__中创建后)。是否可以使用某些库类?或者我是否必须以某种方式为此实现新的有序类?

示例:

d = FixedOrderedDict( ( ("A", 1), ("B", 2) ) )

print d["A"]
# 1
d["A"] = 11
print d["A"]
# 11
d["C"] = 33
# throws exception

我被建议查找名为 FrozenDict 的解决方案,但它使dict为只读 - 无法修改值(在分配新值时抛出异常)。这不是我想要实现的目标。

2 个答案:

答案 0 :(得分:4)

我不知道标准库中的这种解决方案(它是一个相当专业的用例)。但是,您可以使用collections.MutableMapping(3.3及之后的collections.abc.MutableMapping)免费获得大多数功能。给出或采取我现在可能忽略的一些小问题,它只是:

from collections import MutableMapping, OrderedDict

class FixedOrderedDict(MutableMapping):
    def __init__(self, *args):
        self._d = OrderedDict(*args)

    def __getitem__(self, key):
        return self._d[key]

    def __setitem__(self, key, value):
        if key not in self._d:
            raise KeyError("Must not add new keys")
        self._d[key] = value

    def __delitem__(self, key):
        raise NotImplementedError("Must not remove keys")

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

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

答案 1 :(得分:1)

你需要一个dict的子类,它允许你在某些时候冻结键但允许值变异?这个允许你在填充后冻结键,以提供更大的灵活性。

from collections import OrderedDict

class FreezableDict(OrderedDict):
    def __init__(self, *args, **kw):
        super(OrderedDict, self).__init__(*args, **kw)
        self._frozen = False
    def __setitem__(self, key, value):
        if key not in self and self._frozen:
            raise TypeError("No key additions once a FreezableDict is frozen!")
        return super(OrderedDict, self).__setitem__(key, value)
    def freeze(self):
        self._frozen = True

d = FreezableDict((("A", 1), ("B", 2)))

print d["A"]
d["C"] = "New Value"
d.freeze()
d["C"] = "Replacement"
print d["C"]
d["D"] = "This raises a TypeError exception"

但是要小心,要记住并非所有方法都包含在此处,并且它不会尝试完全模拟OrderedDict - 代码假定所有继承的方法都能正常运行。例如,即使冻结后,目前仍允许删除项目。