
On 27.12.2015 04:07, Andrew Barnert via Python-ideas wrote:
This idea seems to come up regularly, so maybe it would be good to actually discuss it out (and, if necessary, explicitly reject it). Most recently, at https://github.com/ambv/typehinting/issues/170, Guido said:
FWIW, maybe we should try to deprecate supporting iteration using the old-style protocol? It's really a very old backwards compatibility measure (from when iterators were first introduced). Then eventually we could do the same for reversing using the old-style protocol.
The best discussion I found was from a 2013 thread (http://article.gmane.org/gmane.comp.python.ideas/23369/), which I'll quote below.
Anyway, the main argument for eliminating the old-style sequence protocol is that, unlike most other protocols in Python, it can't actually be checked for (without iterating the values). Despite a bunch of explicit workaround code (which registers builtin sequence types with `Iterable`, checks for C-API mappings in `reversed`, etc.), you still get false negatives when type-checking types like Steven's at runtime or type-checking time, and you still get false positives from `iter` and `reversed` themselves (`reversed(MyCustomMapping({1:2, 3:4}))` or `iter(typing.Iterable)` won't give you a `TypeError`, they'll give you a useless iterator--which may throw some other exception later when trying to iterate it, but even that isn't reliable).
I'm not sure I follow. The main purpose of ABCs was to be able to explicitly define a type as complying to the sequence, mapping, etc. protocols by registering the class with the appropriate ABCs.
https://www.python.org/dev/peps/pep-3119/
The "sequence protocol" is defined by the Sequence ABC, so by running an isinstance(obj, collections.abc.Sequence) check you can verify the protocol compliance.
Now, most of your email talks about iteration, so perhaps you're referring to a different protocol, that of iterating over arbitrary objects which implement .__getitem__(), but don't implement .__iter__() or .__len__().
However, the support for the iteration protocol is part of the Sequence ABC, so there's no way to separate the two. A Sequence must implement .__len__() as well as .__getitem__() and thus can always implement .__reversed__() and .__iter__().
An object which implements .__getitem__() without .__len__() is not a Python sequence (*).
Overall, the discussion feels somewhat arbitrary to me and is perhaps caused more by a misinterpretation or vague documentation which would need to be clarified, than by an actually missing feature in Python, paired with an important existing practical need :-)
Putting all this together, I believe you're talking about the iter() support for non-sequence, indexable objects. We don't have an ABC for this:
https://docs.python.org/3.5/library/collections.abc.html#collections-abstrac...
and can thus not check for it.
(*) The CPython interpreter actually has a different view on this. It only checks for a .__getitem__() method, not a .__len__() method, in PySequence_Check(). The length information is only queried where necessary and a missing implementation then results in an exception.