I just remembered that the last few times related things came up, I wrote some blog posts going into details that I didn't want to have to dump on the list:
The one about Swift-style map and filter views is, I think, the most interesting here. The tl;dr is that views (lazy sequences) are nifty, and there's nothing actually stopping Python for using them in more places, but they do add complexity, and the benefits probably don't outweigh the costs.
> On Wednesday, September 30, 2015 11:26 AM, Andrew Barnert <firstname.lastname@example.org> wrote:
> > On Sep 30, 2015, at 11:11, M.-A. Lemburg <email@example.com> wrote:
>>> On 30.09.2015 19:19, Neil Girdhar wrote:
>>> I guess, I'm just asking for enumerate to go through the same
> change that
>>> range went through. Why wasn't it a problem for range?
>> range() returns a list in Python 2 and a generator in Python 3.
> No it doesn't. It returns a (lazy) sequence. Not a generator, or any other
> kind of iterator.
> I don't know why so many people seem to believe it returns a generator.
> (And, when you point out what it returns, most of them say, "Why was that
> changed from 2.x xrange, which returned a generator?" but xrange never
> returned a generator either--it returned a lazy almost-a-sequence from the
> There's no conceptual reason that Python couldn't have more lazy
> sequences, and tools to build your own lazy sequences more easily.
> However, things do get messy once you get into the details. For example, zip can
> return a lazy sequence if given only sequences, but what if it's given
> iterators, or other iterables that aren't sequences; filter can return
> something that's sort of like a sequence in that it can be repeatedly
> iterated but it can't be randomly-accessed. You really need a broader
> concept that integrates iteration and indexing, as in the C++ standard library.
> Swift provides the perfect example of how you could do something like that
> without losing the natural features of Python indexing and iteration. But it
> turns out to be complicated to explain, and to work with, and you end up writing
> multiple implementations for each iterable-processing function. I don't
> think the benefit is worth the cost.
> Another alternative is just to wrap any iterable in a caching LazyList type.
> This runs into complications because there are different choices that make sense
> for different uses (obviously you have to handle negative indexing, and
> obviously you have to handle infinite lists, so... Oops!), so it makes more
> sense to leave that up to the application to supply whatever lazy list type it
> needs and use it explicitly.