11import itertools
22import warnings
3+ import weakref
34
45from math import log
56from collections .abc import Iterable
@@ -169,6 +170,7 @@ def __init__(self, attributes, class_vars=None, metas=None, source=None):
169170 self .anonymous = False
170171
171172 self ._hash = None # cache for __hash__()
173+ self ._eq_wdict = {} # cache for __eq__()
172174
173175 def _ensure_indices (self ):
174176 if self ._indices is None :
@@ -185,6 +187,7 @@ def __setstate__(self, state):
185187 self ._variables = self .attributes + self .class_vars
186188 self ._indices = None
187189 self ._hash = None
190+ self ._eq_wdict = {}
188191
189192 def __getstate__ (self ):
190193 # Do not pickle dictionaries because unpickling dictionaries that
@@ -195,6 +198,7 @@ def __getstate__(self):
195198 del state ["_variables" ]
196199 del state ["_indices" ]
197200 del state ["_hash" ]
201+ del state ["_eq_wdict" ]
198202 return state
199203
200204 # noinspection PyPep8Naming
@@ -518,11 +522,30 @@ def __eq__(self, other):
518522 if not isinstance (other , Domain ):
519523 return False
520524
521- return (self .attributes == other .attributes and
522- self .class_vars == other .class_vars and
523- self .metas == other .metas )
525+ # cache by ID because
526+ eq = _idcache_restore (self ._eq_wdict , (other ,))
527+ if eq is None :
528+ eq = (self .attributes == other .attributes and
529+ self .class_vars == other .class_vars and
530+ self .metas == other .metas )
531+ _idcache_save (self ._eq_wdict , (other ,), eq )
532+
533+ return eq
524534
525535 def __hash__ (self ):
526536 if self ._hash is None :
527537 self ._hash = hash (self .attributes ) ^ hash (self .class_vars ) ^ hash (self .metas )
528538 return self ._hash
539+
540+
541+ def _idcache_save (cachedict , keys , value ):
542+ cachedict [tuple (map (id , keys ))] = \
543+ value , [weakref .ref (k ) for k in keys ]
544+
545+
546+ def _idcache_restore (cachedict , keys ):
547+ shared , weakrefs = cachedict .get (tuple (map (id , keys )), (None , []))
548+ for r in weakrefs :
549+ if r () is None :
550+ return None
551+ return shared
0 commit comments