[Python-ideas] Changing `Sequence.__contains__`

Andrew Barnert abarnert at yahoo.com
Mon Jul 21 03:52:58 CEST 2014


On Sunday, July 20, 2014 6:42 PM, Steven D'Aprano <steve at pearwood.info> wrote:

> > On Sun, Jul 20, 2014 at 03:06:33PM -0700, Ram Rachum wrote:
> 
>>  Why does the default `Sequence.__contains__` iterate through the items 
>>  rather than use `.index`, which may sometimes be more efficient?
> 
> Because having an index() method is not a requirement to be a sequence. 
> It is optional. 

Sequence.__contains__ certainly can assume that your class will have an index method, because it provides one if you don't. See https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes (and you can look all the way back to 2.6 and 3.0 to verify that it's always been there).

The default implementation looks like this:

   for i, v in enumerate(self):
        if v == value:
            return i
   raise ValueError


> but it has at two problems I can see:

> 
> - it's not backwards compatible with sequence types which may already 
> define an index attribute which does something different, e.g.:
> 
>     class Book:
>         def index(self):
>             # return the index of the book

This isn't a Sequence. You didn't inherit from collections.abc.Sequence, or even register with it. So, Sequence.__contains__ can't get called on your class in the first place.

If you _do_ make it a Sequence, then you're violating the protocol you're claiming to support, and it's your own fault if that doesn't work. You can also write a __getitem__ that requires four arguments and call yourself a Sequence, but you're going to get exceptions all over the place trying to use it.

> For a historical view, you should be aware that until recently, tuples 

> had no index method:


That was true up until the collections ABCs were aded in 2.6 and 3.0. Prior to that, yes, the "sequence protocol" was a vague thing, and you couldn't be sure that something had an index method just because it looked like a sequence—but, by the same token, prior to that, there was no Sequence ABC mixin, so the problem wasn't relevant in the first place.


More information about the Python-ideas mailing list