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)