Why is nested dictionaries OK, but nested blocks are not allowed?
Why is nested dictionaries allowed in Python, but nested sets are not allowed?
You can insert dictionaries and change sub-dictionaries on the fly, as shown below:
In [1]: dict1 = {'x':{'a':1, 'b':2}, 'y':{'c':3}}
In [2]: dict2 = {'x':{'a':1, 'b':2}, 'y':{'c':3}}
In [3]: dict1 == dict2
Out[3]: True
In [4]: dict2['x'] = {'d':4}
In [5]: dict1 == dict2
Out[5]: False
On the other hand, if you try to put a set in a set, you will get an error saying that this is not possible, since sets are an "unpacked type":
In [6]: set([set(['a'])])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-8e7d044eec15> in <module>()
----> 1 set([set(['a'])])
TypeError: unhashable type: 'set'
But that doesn't make sense as dictionaries don't shake either,
In [7]: hash({'a':1})
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-11-44def9788331> in <module>()
----> 1 hash({'a':1})
TypeError: unhashable type: 'dict'
Of course, you can install a fenizset inside the kit,
In [8]: set([frozenset(['a'])])
Out[8]: {frozenset({'a'})}
but then you cannot subsequently change the internals of the nested frozenset like you could for nested dictionaries.
As per what I found set
and dict
implemented with a hash table under the hood, so I don't understand why this is valid in one case but not in another.
source to share
The problem is, your examples are not similar. No restrictions on dictionary values , only on keys... Here's a more accurate comparison:
>>> d = {{'a': 'b'}: 'c'}
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
d = {{'a': 'b'}: 'c'}
TypeError: unhashable type: 'dict'
>>> s = {{'a': 'b'}, 'c'}
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
s = {{'a': 'b'}, 'c'}
TypeError: unhashable type: 'dict'
Note that you now get the same behavior as expected; you can think of set
as key only dict
.
You cannot use a mutable / non-removable object as a key in a dictionary or an item in a set, because if you change it in place, it becomes unrecoverable (Python matches __eq__
and __hash__
), so these methods must be implemented to use the custom class as key / element). For more on this, see, for example, Why should dictionary keys be immutable? (different language, but the same principle - all hash tables).
You might also consider looking at The Mighty Dictionary if you're interested in the topic.
source to share
Since the hash of an item must be unique for its lifetime in order to be meaningfully stored in the hash table, set
(and also list
) cannot be a member set
, as you noticed. However, the dict
object that gets hashed is the key, not the value. Hence, it is legal:
{'x': {1, 2, 3}} # a string is hashable
and it is not:
{{1, 2, 3}: 'x'}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-1cd059738afd> in <module>()
----> 1 {{1, 2, 3}: 'x'}
TypeError: unhashable type: 'set'
This is also true for other types neraspakovyvaemyh ( list
and dict
).
source to share