On May 14, 2020, at 03:35, Steven D'Aprano <[email protected]> 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?
Because the whole point of this is for something to apply slicing syntax to.
And compare:
lst.view[10:20]
view(lst)[10:20]
vjew(lst, 10, 20)
The last one is clearly the worst, because it doesn’t let you use slicing
syntax.
The others are both OK, but the first seems the most readable. I’ll give more
detailed reasons below. (There may be reasons why it can’t or shouldn’t be
done, which is why I ranked all of the options in order rather than just
insisting that we must have the first one or I hate his whole idea.)
> 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,
But len doesn’t solve that problem at all, and isn’t meant to. It just means
that every sequence type has to implement __len__ instead of every sequence
type having to implement len.
Protocols often provide some added functionality. iter() doesn’t just call
__iter__, it can also fall back to old-style sequence methods, and it has the
2-arg form. Similarly, str() falls back to __repr__, and has other parameter
forms, and doubles as the constructor for the string type. And next() even
changed from being a normal method to a protocol and function, breaking
backward compatibility, specifically to make it easier to do the 2-arg form.
But len() isn’t like that. There is no fallback, no added behavior, nothing. It
doesn’t add anything. So why do we have it? Guido’s argument is in the FAQ. It
starts off with “For some operations, prefix notation just reads better than
postfix”. He then backs up the general principle that this is sometimes true by
appeal to math. And then he explains the reasons this is one of those
operations by arguing that “len”’is the most important piece of information
here so it belongs first.
It’s the same principle here, but the specific answer is different. View-ness
is not more important than the sequence and the slicing, so it doesn’t call out
to be fronted. In fact, view-ness is (at least in the user’s mind) strongly
tied to the slicing, so it calls out to be near the slice.
And it’s not like this is some unprecedented thing. Most of the collection
types, and corresponding ABCs, have regular methods as well as protocol
dunders. Is anyone ever confused by having to write xs.index(x) instead of
index(xs, x)? I don’t think so. In fact, I think the latter would be _more_
confusing, because “index” has so many different meanings that “list.index” is
useful to nail it down. (Notice that we already _have_ a dunder named
__index__, and it does something totally different…) And the same is true for
“view”. In fact, everything in your argument is so generic that it acts as an
argument against not just .index() but against any public methods or attributes
on anything. Obviously you didn’t intend it that way, but once you actually
target it so that it argues against .len() but not .index(), I don’t think
there’s any argument against .view left.
> and that's why in the Java world nobody agrees what method to call to
> get the length of an object.
Nobody can agree on what function to call in C or PHP even though they’re
functions rather than methods in those languages.
Everyone can agree on what method to use in C++ and Smalltalk even though
they’re methods in those languages, just like Java. (In fact, C++ even loosely
enforces consistency the same way Python loosely does, except at compile time
instead of run time—if your class doesn’t have a size() method, it doesn’t duck
type as a collection and therefore can’t be used in templates that want a
collection.)
Or just look at Python: nobody is confused about how to spell the .index method
even though it’s a method.
So the problem in Java has nothing to do with methods. (We don’t have to get
into what’s wrong with Java here; it’s not relevant.)
> So if we are to have a generic view proxy object, as opposed to the very
> much non-generic dict views, then it ought to be a callable function
We don’t actually _know_ how generic it can/should be yet. That’s something
we’ve been discussing in this thread. It might well be a
quality-of-implementation issue that has different best answers in different
Pythons. Or it might not. It’s not obvious. Which implies that whatever the
answer is, it’s not something that people should have to grasp it to understand
the feature.
You wouldn’t want to users to base their understanding of iter on knowing
whether there’s one generic sequence iterator type or one for each type
(especially since neither is true in CPython, but something halfway between and
more complicated). And I think the same is true here. So you’re arguing for a
callable function because it strongly implies a generic implementation, but I
see that as an argument _against_ a function, not for it, and I also don’t
think the argument holds anyway because it doesn’t imply any such thing for
iter.
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/RUR25QPBCANNSH2V7JHMX2EW7LBWLWHS/
Code of Conduct: http://python.org/psf/codeofconduct/