[Python-ideas] __iter__ implies __contains__?

Masklinn masklinn at masklinn.net
Sun Oct 2 13:28:53 CEST 2011


On 2011-10-02, at 03:14 , Steven D'Aprano wrote:
> These changes don't sound even close to reasonable to me. It seems to me that the OP is making a distinction that doesn't exist.
> 
> If you can write this:
> 
> x = collection[0]; do_something_with(x)
> x = collection[1]; do_something_with(x)
> x = collection[2]; do_something_with(x)
> # ... etc.
> 
> then you can write it in a loop by hand:
> 
> i = -1
> try:
>    while True:
>        i += 1
>        x = collection[i]
>        do_something_with(x)
> except IndexError:
>    pass
> 
> But that's just a for-loop in disguise. The for-loop protocol goes all the way back to Python 1.5 and surely even older. You should, and can, be able to write this:
> 
> for x in collection:
>    do_something_with(x)
> 
> Requiring collection to explicitly inherit from a Sequence ABC breaks duck typing and is anti-Pythonic.
> 
> I can't comprehend a use-case where manually extracting collection[i] for sequential values of i should succeed
You can write this:

x = collection['foo']; do_something_with(x)
x = collection['bar']; do_something_with(x)
x = collection['baz']; do_something_with(x)

you can't write either of the other two options, but since Python calls the exact same method, if you somehow do a containment check (or an iteration) of a simple k:v collection instead of getting a clear exception about a missing `__iter__` or `__contains__` you get a not-very-informative `KeyError: 0` 3 or 4 levels down the stack, and now have to hunt how in hell's name somebody managed to call `collection[0]`.


More information about the Python-ideas mailing list