-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
I think many python programmers think of an iterable as a container of items that allows several passes through it. In other words, they would think the following code is correct:
def count_max_values(iterable: Iterable) -> int:
"""Count the number of times the maximum value appears in iterable"""
max_value = max(iterable, default=None)
counter = 0
for item in iterable:
if item == max_value:
counter += 1
return counter
Obviously, if the argument was an Iterator, there would be no doubt that the above implementation is incorrect.
However, at the moment, the following code would pass the type check:
iter = (i for i in range(5))
count_max_values(iter)
The reason is that the definition of Iterable is currently only concerned with the presence of __get_item__() or __iter__() methods, and so every Iterator is automatically an Iterable.
Would it be worth redefining Iterator and Iterable? For example, the rule could be that if an object defines both __iter__ and __next__ methods, it is not an Iterable (since it's very weird for an iterable to have a __next__ method); otherwise, if it defines __iter__ or __getitem__, it is an Iterable. If necessary, an option could be given to the programmer to explicitly override this rule (marking as Iterable an object with both __iter__ and __next__; or as not Iterable an object with __iter__ and without __next__).