Protocols in Python

Chris Angelico rosuav at gmail.com
Mon Aug 28 16:06:50 EDT 2017


On Tue, Aug 29, 2017 at 4:53 AM, Stefan Ram <ram at zedat.fu-berlin.de> wrote:
> ram at zedat.fu-berlin.de (Stefan Ram) writes:
>>The "The Python Library Reference, Release 3.6.0" (LIB) says:
>>»it must support the sequence protocol (the
>>__getitem__() method with integer arguments
>>starting at 0).«.
>>But in the "The Python Language Reference, Release 3.6.0"
>>(LANG) this is called »old sequence iteration« or »old-style
>>iteration« with the (new) sequence protocol being augmented
>>by »__len__«.
>
>   Can one say that the authoritative test for being »iterable«
>   and being »a sequence« is testing whether the object is an
>   instance of »collections.abc.Iterable« and
>   »collections.abc.Sequence«, respectively?
>
>   Some parts of the references explain that implementing the
>   sequence protocol means to have a »__getitem__« method and
>   possibly also a »__len__« method. But, by inheritance,
>   »collections.abc.Sequence« seems to require /more/. I.e.,
>
>>>> import collections.abc
>
>>>> d = { 1: 2 }
>
>>>> d.__len__
> <method-wrapper '__len__' of dict object at 0x00000000023578B8>
>
>>>> d.__getitem__
> <built-in method __getitem__ of dict object at 0x00000000023578B8>
>
>>>> isinstance( d, collections.abc.Sequence )
> False
>
>   And the reference does /not/ list dictionary under "Sequences".

A dictionary isn't a sequence. At very least, you have to be able to
start with d[0] and go up from there; and that is indeed a valid
*iterable* protocol:

>>> class Demo:
...     def __getitem__(self, item):
...         item = int(item)
...         if 0 <= item < 10: return item * item
...         raise IndexError
...
>>> list(Demo())
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

But that isn't a sequence still. Be careful that you aren't looking at
*iterable* protocol instead.

ChrisA



More information about the Python-list mailing list