不可变的字典,仅用作其他字典的键

发布于 2021-01-29 18:15:01

我需要实现一个可哈希的字典,因此我可以将一个字典用作另一个字典的键。

但是我从一位同事那里得到了一个通知,说“它并不是真正不变的,因此并不安全。您可以使用它,但是它的确使我感到自己像个可悲的熊猫。

因此,我开始环顾四周以创建一个不可变的对象。我没有必要将“ key-dict”与另一个“ key-dict”进行比较。它的唯一用途是用作另一本词典的键。

我想出了以下几点:

class HashableDict(dict):
    """Hashable dict that can be used as a key in other dictionaries"""

    def __new__(self, *args, **kwargs):
        # create a new local dict, that will be used by the HashableDictBase closure class
        immutableDict = dict(*args, **kwargs)

        class HashableDictBase(object):
            """Hashable dict that can be used as a key in other dictionaries. This is now immutable"""

            def __key(self):
                """Return a tuple of the current keys"""
                return tuple((k, immutableDict[k]) for k in sorted(immutableDict))

            def __hash__(self):
                """Return a hash of __key"""
                return hash(self.__key())

            def __eq__(self, other):
                """Compare two __keys"""
                return self.__key() == other.__key() # pylint: disable-msg=W0212

            def __repr__(self):
                """@see: dict.__repr__"""
                return immutableDict.__repr__()

            def __str__(self):
                """@see: dict.__str__"""
                return immutableDict.__str__()

            def __setattr__(self, *args):
                raise TypeError("can't modify immutable instance")
            __delattr__ = __setattr__

        return HashableDictBase()

我使用以下工具测试功能:

d = {"a" : 1}

a = HashableDict(d)
b = HashableDict({"b" : 2})

print a
d["b"] = 2
print a

c = HashableDict({"a" : 1})

test = {a : "value with a dict as key (key a)",
        b : "value with a dict as key (key b)"}

print test[a]
print test[b]
print test[c]

这使:

{‘a’:1}
{‘a’:1}
以dict为键(键a)的
值以dict为键(键b)的
值以dict为键(键a)的值

作为输出

这是我可以使用的“最佳”不可变字典,它满足我的要求吗?如果没有,什么是更好的解决方案?

关注者
0
被浏览
45
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    如果仅将它用作其他项的密钥dict,则可以这样做frozenset(mutabledict.items())。如果您需要访问基础映射,则可以将其用作的参数dict

    mutabledict = dict(zip('abc', range(3)))
    immutable = frozenset(mutabledict.items())
    read_frozen = dict(immutable)
    read_frozen['a'] # => 1
    

    请注意,您还可以将此方法与从派生的类结合dict使用,并frozenset在禁用的同时将用作哈希的源__setitem__,如另一个答案中所建议。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看