When comparing nested lists with <, it first checks equality (==) of elements at each level to find where they differ before doing the actual ordering comparison. For nested structures, this means __eq__ gets called once per nesting level—even though only one comparison determines the result. Your example shows 100 calls because Python checks equality through all 100 layers before realizing X(1) < X(0) is false.
How about precompute a lightweight comparison key during initialization? For cases like chemical formulas (where equality is complex due to multiple representations), canonicalize the value once—e.g., sort atoms into a standard order—and store that key.
class X:
def __init__(self, value):
self.value = value
self._key = self._canonicalize(value)
def _canonicalize(self, value):
return tuple(sorted(value))
def __lt__(self, other):
return self._key < other._key
def __eq__(self, other):
return self._key == other._key
nested_x1 = [[[X("C2H6")]]]
nested_x2 = [[[X("C2H5OH")]]]
print(nested_x1 < nested_x2) # Fast: compares keys, not raw values
If your data can't be pre-canonicalized (e.g., disk-backed values), consider lazy key generation with memoization—but for most cases, a one-time key computation solves the algorithmic redundancy cleanly.