Deprecate "old-style iteration protocol"?

Let’s not break code that relies on the sequence protocol just to cover up a side-effect of writing an unusual, and potentially dangerous, class.

The problem here is that your “identity dict” behaves as an infinite lazy sequence. There is nothing wrong with infinite lazy sequences, but you can’t call list() on them.

from itertools import count  # Another infinite lazy sequence.

c = count()
list(c)  # Iterates forever.

Be warned that iterating over count() seems to be uninterruptable, at least when I tried it, and so you may need to kill the terminal it is running in.

A better idea, in my opinion, would be a protocol that iterators and lazy sequences can signal to consumers that they are infinite. We already have a __len_hint__, perhaps we could use that. That would still allow iteration in for-loops, but prevent “all steam ahead” iteration to exhaustion into a list, tuple, set etc.

The solution for identity_dict is to give it an __iter__ method. You can’t meaningfully iterate over the keys, so let’s prevent it:

class identity_dict:
    def __getitem__(self, key):
        return key

    __iter__ = None  # Prevent iteration.

The bottom line here is that there is nothing wrong with iteration using the sequence protocol, nothing wrong with looping over a lazy infinite sequence or iterator, but there is a problem when you try to instantiate such an infinite sequence of values into a list, set or other finite collection. We should determine a way that such finite collections can identify such infinite iterators up front.

2 Likes