On Thu, May 14, 2020 at 3:32 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Sun, May 10, 2020 at 09:36:14PM -0700, Andrew Barnert via Python-ideas wrote:
> > for i in itertools.seq_view(a_list)[::2]:
> >     ...
> >
> > I still think I prefer this though:
> >
> > for i in a_list.view[::2]:

> Agreed. A property on sequences would be best,

Why?

This leads to the same problem that len() solves by being a function,
not a method on list and tuple and str and bytes and dict and deque and
.... Making views a method or property means that every sequence type
needs to implement it's own method, or inherit from the same base class,
and that's why in the Java world nobody agrees what method to call to
get the length of an object.

I'm not a Java guy -- but I'm not sure that's the problem -- it sounds to me like Java does have clearly defined Interfaces (that's the Java concept, yes?) for Sequences, or, in this case, "Sized". Granted, len() as a builtin pre-dates ABCs, but we do have them now, and we do for a reason.
 
Python has a long history of using protocols and optional dunders for
things like this:

https://lucumr.pocoo.org/2011/7/9/python-and-pola/

Nice post, and I agree for teh most part, but frankly, I dont find it convicing. For example:

"In Ruby collection objects respond to .size. But because it looks better almost all of them will also respond .length."

And really? Java and Ruby both have these inconsistencies in the standard library? WTF?

And why do we not have: "In Python, collection objects response to the len() function. But because it looks better, almost all of them will also have a .size property. I think it's more about "Python has a long history of using protocols", which I interpret to mean "people follow standards" (at least in the standard library!) , rather than "you have to use built in functions for any operation that might be applicable to more than one type"

And despite that history, the ABCs DO have a few regular methods, and a bunch of mixins.

And frankly, I don't really see the difference in terms of ease of implementation -- one way and all Sequences need to implement .view (or use the ABC mixin), and one they need to implement __view__ (or use the ABC mixin).

Though as I write this, I realize, of course, that there IS an advantage to __view__ -- the dunders are a reserved namespace, so no one should have a custom Sequence that already has a .__view__ dunder. Whereas third party Sequences *may* already have a .view attribute. Indeed, numpy arrays do, and it does NOT mean the same thing that this would.

Funny, if I go back to that post, it turns out I didn't find the whole "Java and Ruby haven't standardize on how to spell length" argument compelling, but later, he talks about how the dunders are reserved -- and THAT is, indeed, compelling.

So that means a view() function (with maybe a different name) -- however, that brings up the issue of where to put it. I'm not sure that it warrants being in builtins, but where does it belong? Maybe the collections module? And I really think the extra import would be a barrier.

Going back to the whole functions and protocols vs methods argument, the fact is that I don't think there IS a clear line between what belongs where. Let's face it, I don't think any of us would like it if we had to do something like:

from collections import keys, values

the_keys = keys(a_dict)

And I think we all agree that moving string functionality into str methods was a really good idea.

In fact, I think that when adding stuff to builtins, particularly ABC, we are stuck not with deciding where is best belongsl, but simiply with -- it can't be a method if it wasn't there near the beginning of Python's life.

> So if we are to have a generic view proxy object, as opposed to the very
much non-generic dict views,

I still don't think that the "genericness" is the point here. A Sequence view isn't really any more generic than a MappingView, the difference in API is that Mappings have had .keys() and .values() and .items() forever, so it was possible to change what they return without potentially breaking other implementations. (that was also a py2-py3 change, which allowed more breakage).

It would be kin do like changing what indexing with a slice meant -- but we are not advocating that!

Growing a language is a challenge!

-CHB

--
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython