Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable dictionary in Python 3: how to make keys(), items(), and values() dictionary views immutable

Short version: What's the best way to override dict.keys() and friends to keep myself from accidentally modifying my (supposedly) immutable dictionary in Python 3?

In a recent question I asked about Hashing an immutable dictionary in Python. Since then I have built an immutable, hashable dictionary I'm happy with. However, I realized it has a hole: the dictionary views returned by keys(), items(), and values() still allow myself accidentally to mutate my (supposedly) immutable dictionary.

The only question on Stack Overflow I could find about dictionary views was Python create own dict view of subset of dictionary, but that didn't seem to have much to do with my problem, and the answers to What would a "frozen dict" be? didn't seem to get into overriding keys(), etc.

Would doing something like this prevent me from accidentally modifying, for example, the keys of my immutable dictionary?

class FrozenCounter(collections.Counter):
    "Model an hashable multiset as an immutable dictionary."
    # ...
    def keys(self):
        return list(super().keys())
    def values(self):
        return list(super().values())
    def items(self):
        return list(super().items())


What I've gathered from the answers

I can't read, mainly.

dictviews cannot modify dicts. In the Python 3 documentation, I misread, "They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes" as saying "when the view changes, the dictionary reflects these changes." Obviously that is not what the documentation said.

like image 609
wkschwartz Avatar asked Apr 11 '12 17:04

wkschwartz


People also ask

Are values and keys in dictionaries immutable?

The keys are immutable. Just like lists, the values of dictionaries can hold heterogeneous data i.e., integers, floats, strings, NaN, Booleans, lists, arrays, and even nested dictionaries.

Why can only immutable values be used as keys in a Python dictionary?

Values can be any type of object, but keys must be immutable. This means keys could be integers, strings, or tuples, but not lists, because lists are mutable. Dictionaries themselves are mutable, so entries can be added, removed, and changed at any time.

Are Keys in dictionary immutable Python?

As shown in the figure below, keys are immutable ( which cannot be changed ) data types that can be either strings or numbers. However, a key can not be a mutable data type, for example, a list. Keys are unique within a Dictionary and can not be duplicated inside a Dictionary.

Can we create immutable dictionary in Python?

No, it can't. The object can be made mutable (or not) irrespective of what its __hash__ method does. The relationship between immutable objects and __hash__ is that, since an immutable object cannot be changed, the value returned by __hash__ remains constant post-construction.


1 Answers

In Python 2.x, views don't allow you to mutate your underlying object:

>>> a = { 'a' : 1 }
>>> a.keys()[0] = 'b'
>>> a
{'a': 1}
>>> a.values()[0] = 'b'
>>> a
{'a': 1}

In Python 3.x, mutating views gives a TypeError:

>>> a = { 'a':1}
>>> a.keys()[0] = 'b'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dict_keys' object does not support item assignment
like image 58
user1202136 Avatar answered Sep 28 '22 01:09

user1202136