This module proposes hashable version of the mutable containers
list, dict and set, called respectively hlist, hdict and
hset.
After one object has been hashed, it becomes not mutable and raises a
ValueError if a method which changes the object (let call a
mutation such a method) is invoqued. The object can be then
un-hashed by calling unhash on it so that it becomes mutable again.
Notice that this may cause troubles if the object is stored in a set
or dict which uses its hashcode to locate it. Notice also that
hashable containers cannot be hashed if they contain non hashable
objects.
>>> l = hlist(range(5))
>>> l
hlist([0, 1, 2, 3, 4])
>>> _ = hash(l)
>>> l.append(5)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> unhash(l)
>>> l.append(5)
>>> l
hlist([0, 1, 2, 3, 4, 5])
Testing if a hlist is in a set, dict, hset or hdict causes
its hashing. If this is not desirable, you should either compensate
with a call to unhash, or test if a copy is in the set:
>>> s = set()
>>> s.add(list(range(4)))
Traceback (most recent call last):
...
TypeError: ...
>>> s.add(hlist(range(4)))
>>> l = hlist(range(3))
>>> l in s
False
>>> l.append(3)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> unhash(l)
>>> l.append(3)
>>> l[:] in s
True
>>> l.append(4)
Function unhash
def unhash (obj) :
Make the object mutable again. This should be used with caution, especially if the object is stored in a dict or a set.
>>> l = hlist(range(3))
>>> _ = hash(l)
>>> l.append(3)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> unhash(l)
>>> l.append(3)
Call API
object obj: any object
Class hlist
class hlist (list) :
Hashable lists. They support all standard methods from list.
>>> l = hlist(range(5))
>>> l
hlist([0, 1, 2, 3, 4])
>>> l.append(5)
>>> l
hlist([0, 1, 2, 3, 4, 5])
>>> _ = hash(l)
>>> l.append(6)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> unhash(l)
>>> l.append(6)
Class hdict
class hdict (dict) :
Hashable dictionnaries. They support all standard methods from
dict.
>>> l = hlist(range(5))
>>> d = hdict([(l, 0)])
>>> d
hdict({hlist([0, 1, 2, 3, 4]): 0})
>>> l in d
True
>>> [0, 1, 2, 3, 4] in d
Traceback (most recent call last):
...
TypeError: ...
>>> hlist([0, 1, 2, 3, 4]) in d
True
>>> d[hlist([0, 1, 2, 3, 4])]
0
>>> l.append(5)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> _ = hash(d)
>>> d.pop(l) # any mutation would produce the same error
Traceback (most recent call last):
...
ValueError: hashed 'hdict' object is not mutable
>>> unhash(d)
>>> d.pop(l)
0
Class hset
class hset (set) :
Hashable sets. They support all standard methods from set.
>>> s = hset()
>>> l = hlist(range(5))
>>> s.add(l)
>>> s
hset([hlist([0, 1, 2, 3, 4])])
>>> l in s
True
>>> [0, 1, 2, 3, 4] in s
Traceback (most recent call last):
...
TypeError: ...
>>> hlist([0, 1, 2, 3, 4]) in s
True
>>> l.append(5)
Traceback (most recent call last):
...
ValueError: hashed 'hlist' object is not mutable
>>> _ = hash(s)
>>> s.discard(l) # any mutation would produce the same error
Traceback (most recent call last):
...
ValueError: hashed 'hset' object is not mutable
>>> unhash(s)
>>> s.discard(l)