On Sun, Jul 26, 2020 at 12:31:17PM -0500, Henry Lin wrote:
> Hi Steven,
>
> You're right, declaring `__eq__` for the class we want to compare would
> solve this issue. However, we have the tradeoff that
>
> - All classes need to implement the `__eq__` method to compare two
> instances;
One argument in favour of a standard solution would be to avoid
duplicated implementations. Perhaps we should add something, not as a
unittest method, but in functools:
def compare(a, b):
if a is b:
return True
# Simplified version.
return vars(a) == vars(b)
The actual implementation would be more complex, of course. Then classes
could optionally implement equality:
def __eq__(self, other):
if isinstance(other, type(self):
return functools.compare(self, other)
return NotImplemented
or if you prefer, you could call the function directly in your unit
tests:
self.assertTrue(functools.compare(actual, other))
> - Any class implementing the `__eq__` operator is no longer hashable
Easy enough to add back in:
def __hash__(self):
return super().__hash__()
> - Developers might not want to leak the `__eq__` function to other
> developers; I wouldn't want to invade the implementation of my class just
> for testing.
That seems odd to me. You are *literally* comparing two instances for
equality, just calling it something different from `==`. Why would you
not be happy to expose it?
> In terms of the "popularity" of this potential feature, from what I
> understand (and through my own development), there are testing libraries
> built with this feature. For example, testfixtures.compare
> <https://testfixtures.readthedocs.io/en/latest/api.html#testfixtures.compare>
> can compare two objects recursively, and I am using it in my development
> for this purpose.
That's a good example of what we should *not* do, and why trying to
create a single standard solution for every imaginable scenario can only
end up with an over-engineered, complex, complicated, confusing API:
testfixtures.compare(
x, y,
prefix=None,
suffix=None,
raises=True,
recursive=True,
strict=False,
comparers=None,
**kw)
Not shown in the function signature are additional keyword arguments:
actual, expected # alternative spelling for x, y
x_label,
y_label,
ignore_eq
That is literally thirteen optional parameters, plus arbitrary keyword
parameters, for something that just compares two objects.
But a simple comparison function, possibly in functools, that simply
compares attributes, might be worthwhile.
--
Steven
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/56GD3DDO2PLNOB4TIIO7PBJCUPFLGA3V/
Code of Conduct: http://python.org/psf/codeofconduct/