Line | |
---|
1 |
|
---|
2 |
|
---|
3 | from collections.abc import Iterator
|
---|
4 | from itertools import tee
|
---|
5 | from typing import Tuple, List, Collection, Dict, Set, Type
|
---|
6 |
|
---|
7 | def safehash(obj)->int:
|
---|
8 | '''
|
---|
9 | Tool to take a hash of an object in a safe way.
|
---|
10 | The idea is that it intercepts non-hashable types
|
---|
11 | and works around it.
|
---|
12 | '''
|
---|
13 | try:
|
---|
14 | # first try the dumb way, because the safe way is expensive
|
---|
15 | # see also #357
|
---|
16 | return obj.__hash__()
|
---|
17 | except TypeError:
|
---|
18 | # the constants are to distinguish between the types
|
---|
19 | if isinstance(obj, Set): #order irrelevant
|
---|
20 | return 17+sum([safehash(it) for it in obj])
|
---|
21 | if isinstance(obj, Dict): # order irrelevant.
|
---|
22 | return 133+sum([safehash(item) for item in obj.items() ])
|
---|
23 | if isinstance(obj, List) or isinstance(obj, tuple): # order is important
|
---|
24 | return 31+hash( tuple ( safehash(elt) for elt in obj ) )
|
---|
25 | if isinstance(obj, type):
|
---|
26 | return hash(obj)
|
---|
27 | raise ValueError("Type not yet handled: "+str(obj)) |
---|
Note:
See
TracBrowser
for help on using the repository browser.