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)