I expect map() well predates __length_hint__. Maybe when __length_hint__ was implemented nobody thought to do this propagation?
It seams like a reasonable thing to want and since map() is 1-to-1 the
propagation seems like a correct thing to do.
Yes. I explored this path and it was a dead end. See the docstring for test_iterlen. Several problems arose but the biggest is summarized in the last paragraph:
The iterators not listed above, such as enumerate and the other itertools,
are not length transparent because they have no way to distinguish between
iterables that report static length and iterators whose length changes with
each call (i.e. the difference between enumerate(‘abc’) and
For generators, absolutely. The length of a generator is, in general, completely unpredictable, and may be infinite.
This applies to both generator comprehensions and full def ... yield generators. It often will require extremely sophisticated analysis, and even human intelligence, to determine even a hint of what the length might be, and may be impossible to predict.
def collatz(n: int):
if n < 1:
while n > 1:
if n % 2 == 0:
n = n//2
n = 3*n + 1
assert n == 1
It is not even known whether the Collatz sequence terminates for all values of n, let alone how long the sequence is.
Asking the interpreter to compute a __length_hint__ for generators is a waste of time. It would be accurate only in a tiny fraction of cases, and even then only under the most trivial circumstances. It hardly seems like it is worth the effort.
In the case of map, I guess that the length of the map iterator cannot be different from the length of the input. So I suppose we might request an enhancement, the map iterators copy or otherwise expose whatever length hint their input provides.
But… why bother? It’s not that I oppose the suggestion that map iterators forward the length hint, but I do wonder why you want it to?
My main use case was tqdm and other progress bar utilities. To display the estimated progression during iteration, the size of the iterable is required. I discovered that many functions returning map-like objects such as map, enumerate but also ThreadPoolExecutor.map() and many others do not forward __length_hint__. The workaround is simple but quite cumbersome.
Another advantage of length hints being propagated is simply optimization of allocations.
my expectation was that there is no distinction between iterators with a static size vs ones with a dynamic size, operator.length_hint() would simply return the length hint returned by the iterator at the time of the call. Since __length_hint__ is a best effort implementation, in case the length changes it could simply return the length of the original iterable.