[Python-Dev] RE: PySequence_Contains
Guido van Rossum
guido@digicool.com
Sat, 05 May 2001 16:48:33 -0500
> [Guido]
> > This kind of thing happens everywhere -- instances always define all
> > slots but using the slots sometimes fails when the corresponding
> > __foo__ doesn't exist. Decisions based on the presence or absence of
> > a slot are therefore in general not reliable; the only exception is
> > the decision to *call* the slot or not. The correct solution is not
> > to catch AttributeError and pretend that the slot didn't exist (which
> > would mask an AttributeError occurring inside the __contains__ method
> > if there was one),
[Tim]
> Ya, it sucks. I was inspired by that instance_contains() itself makes
> dubious assumptions about what an AttributeError means when the functions
> *it* calls raise it <wink>.
Actually, instance_contains checks for AttributeError only after
calling instance_getattr(), whose only purpose is to return the
requested attribute or raise AttributeError, so here it is safe: the
__contains__ function hasn't been called yet.
> > but to reimplement the default behavior in the instance slot
> > implementation.
>
> The "backward compatibility" comment in instance_contains() was scary:
> compatibility with *what*?
With previous behavior of 'x in instance'. Before we had
__contains__, 'x in y' *always* iterated over the items of y as a
sequence, comparing them to x one at a time. The loop does that.
> instance_contains() is pretty darn new. I
> assumed it meant there was *some* good (but unidentified) reason we had to
> use PyObject_Cmp() instead of PyObject_RichCompareBool(..., Py_EQ) if
> instance_item() "worked".
No, that was probably just an oversight -- clearly it should have used
rich comparisons. (I guess this is a disadvantage of the approach I'm
recommending here: if the default behavior changes, the
reimplementation of the default behavior in the class must be changed
too.)
> But I haven't thought of one, except to ensure
> that
>
> some_complex in some_instance_with___getitem__
>
> continues to blow up -- but that's not a good reason.
Indeed not.
> So:
>
> > In this case, that means that PySequence_Contains() can be simplified
> > (no need to test for AttributeError), and instance_contains() should
> > fall back to a loop over iter(self) rather than trying to use
> > instance_item().
>
> Will do!
Thanks!
--Guido van Rossum (home page: http://www.python.org/~guido/)