Description
Bug report
Bug description:
Brief Description
Optimization done in #109870 changed semantic of dataclass
comparison.
Description
The pseudo code below shows meaning of changes have been done in #109870. The semantic differs largely because of a shortcut in __eq__
implementation of sequence-like containers (see Objects/object.c). The shortcut essentially does self[i] is other[i]
. Consequently, method __eq__
of self[i]
is not evaluated for identical objects in 3.12 during dataclasses.dataclass
comparison.
def __eq__312(self, other):
return astuple(self) == astuple(other)
def __eq__313(self, other):
for lhs, rhs in zip(astuple(self), astuple(other)):
if not lhs == rhs:
return False
else:
return True
According Python docs (citation below), v3.13 introduces breaking change since it does not consider fields as a tuples for dataclass comparison.
eq: If true (the default), an
__eq__()
method will be generated. This method compares the class as if it were a tuple of its fields, in order. Both instances in the comparison must be of the identical type.
Test Case
import numpy as np
from dataclasses import dataclass
@dataclass
class A:
xs: np.ndarray
a = A(np.ones(3))
b = A(a.xs)
print(a == b) # FAIL (3.13); OK (3.12).
# ValueError: Value The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
CPython versions tested on:
3.13 (3.12)
Operating systems tested on:
Linux