[Python-ideas] Fwd: Why do equality tests between OrderedDict keys/values views behave not as expected?

Steven D'Aprano steve at pearwood.info
Fri Dec 18 23:10:11 EST 2015


On Fri, Dec 18, 2015 at 10:43:24PM -0500, Franklin? Lee wrote:
> On Fri, Dec 18, 2015 at 10:38 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> > On Fri, Dec 18, 2015 at 05:59:39PM -0500, Franklin? Lee wrote:
> >
> >> I see two options:
> >> - comparison is explicitly NotImplemented. Any code that used it
> >> should've used `is`.
> >
> > We're still talking about equality between Mapping.values() views,
> > correct?
[...]
> First, failing fast. I see this as a silent error waiting to happen.

Franklin, could you please try to be a little bit more explicit about 
what "it" and "this" is when you describe something? I find it very hard 
to understand what *specific* thing you are referring to when you refer 
to it using short-hand.

You say that "this" is a silent error waiting to happen. Does "this" 
refer to your suggestion that "comparison is explicitly NotImplemented", 
or something else? I can't tell.

 
> Second, "NotImplemented" allows the other side to try its __eq__.

Okay, that makes better sense. I tought you meant that 
Mapping.ValuesView *did not implement* an __eq__ method, so that it 
raised an exception if you tried to compare them:

# What I thought you meant
a.values() == b.values()
=> raises an exception


Now I understand that you mean they should return NotImplemented 
instead. But in practice, that doesn't actually change the behaviour 
that much: if both sides return NotImplemented, Python will fall back to 
the default behaviour, which is identity.

py> class A:
...     def __eq__(self, other):
...             return NotImplemented
...
py> a = A()
py> b = A()
py> a == a
True
py> a == b
False


Returning NotImplemented just allows the other argument a chance to be 
called, but that already happens!

py> class Spam:
...     def __eq__(self, other):
...             print("calling Spam.__eq__")
...             return True
...
py> a = odict()
py> b = Spam()
py> a == b
calling Spam.__eq__
True
py> b == a
calling Spam.__eq__
True


So no change there. We already have that behaviour.



-- 
Steve


More information about the Python-ideas mailing list