New submission from Leopold Talirz <leopold.tal...@epfl.ch>:
Disclaimer: this is my first issue on the python bug tracker. Please feel free to close this issue and redirect this to a specific mailing list, if more appropriate. The implementation of `functools._HashedSeq` [1] does not include an implementation of `__eq__` that takes advantage of the hash: ``` class _HashedSeq(list): """ This class guarantees that hash() will be called no more than once per element. This is important because the lru_cache() will hash the key multiple times on a cache miss. """ __slots__ = 'hashvalue' def __init__(self, tup, hash=hash): self[:] = tup self.hashvalue = hash(tup) def __hash__(self): return self.hashvalue ``` As far as I can tell, the `_HashedSeq` object is used as a key for looking up values in the python dictionary that holds the LRU cache, and this lookup mechanism relies on `__eq__` over `__hash__` (besides shortcuts for objects with the same id, etc.). This can cause potentially expensive `__eq__` calls on the arguments of the cached function and I wonder whether this is intended? Here is a short example code to demonstrate this: ``` from functools import _HashedSeq class CompList(list): """Hashable list (please forgive)""" def __eq__(self, other): print("equality comparison") return super().__eq__(other) def __hash__(self): return hash(tuple(self)) args1=CompList((1,2,3)) # represents function arguments passed to lru_cache args2=CompList((1,2,3)) # identical content but different object hs1=_HashedSeq( (args1,)) hs2=_HashedSeq( (args2,)) hs1 == hs2 # True, prints "equality comparison" d={} d[hs1] = "cached" d[hs2] # "cached", prints "equality comparison" ``` Adding the following to the implementation of `_HashedSeq` gets rid of the calls to `__eq__`: ``` def __eq__(self, other): return self.hashvalue == other.hashvalue ``` Happy to open a PR for this. I'm certainly a bit out of my depth here, so apologies if that is all intended behavior. [1] https://github.com/python/cpython/blob/679cb4781ea370c3b3ce40d3334dc404d7e9d92b/Lib/functools.py#L432-L446 ---------- components: Library (Lib) messages: 400858 nosy: leopold.talirz priority: normal severity: normal status: open title: functools._HashedSeq implements __hash__ but not __eq__ type: behavior versions: Python 3.10, Python 3.9 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue45080> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com