Define a python dictionary with immutable keys but mutable values

前端 未结 3 1684
陌清茗
陌清茗 2021-01-04 10:04

Well, the question is in the title: how do I define a python dictionary with immutable keys but mutable values? I came up with this (in python 2.x):

class Fi         


        
相关标签:
3条回答
  • 2021-01-04 10:30

    How you prevent someone from adding new keys depends entirely on why someone might try to add new keys. As the comments state, most dictionary methods that modify the keys don't go through __setitem__, so a .update() call will add new keys just fine.

    If you only expect someone to use d[new_key] = v, then your __setitem__ is fine. If they might use other ways to add keys, then you have to put in more work. And of course, they can always use this to do it anyway:

    dict.__setitem__(d, new_key, v)
    

    You can't make things truly immutable in Python, you can only stop particular changes.

    0 讨论(0)
  • 2021-01-04 10:31

    The problem with direct inheritance from dict is that it's quite hard to comply with the full dict's contract (e.g. in your case, update method won't behave in a consistent way).

    What you want, is to extend the collections.MutableMapping:

    import collections
    
    class FixedDict(collections.MutableMapping):
        def __init__(self, data):
            self.__data = data
    
        def __len__(self):
            return len(self.__data)
    
        def __iter__(self):
            return iter(self.__data)
    
        def __setitem__(self, k, v):
            if k not in self.__data:
                raise KeyError(k)
    
            self.__data[k] = v
    
        def __delitem__(self, k):
            raise NotImplementedError
    
        def __getitem__(self, k):
            return self.__data[k]
    
        def __contains__(self, k):
            return k in self.__data
    

    Note that the original (wrapped) dict will be modified, if you don't want that to happen, use copy or deepcopy.

    0 讨论(0)
  • 2021-01-04 10:47

    Consider proxying dict instead of subclassing it. That means that only the methods that you define will be allowed, instead of falling back to dict's implementations.

    class FixedDict(object):
            def __init__(self, dictionary):
                self._dictionary = dictionary
            def __setitem__(self, key, item):
                    if key not in self._dictionary:
                        raise KeyError("The key {} is not defined.".format(key))
                    self._dictionary[key] = item
            def __getitem__(self, key):
                return self._dictionary[key]
    

    Also, you should use string formatting instead of + to generate the error message, since otherwise it will crash for any value that's not a string.

    0 讨论(0)
提交回复
热议问题