[Python-ideas] Possible new slice behaviour? Was ( Negative slice discussion.)
Ron Adam
ron3200 at gmail.com
Tue Nov 5 02:48:06 CET 2013
On 11/04/2013 04:40 PM, Nick Coghlan wrote:
>
>
> On 5 Nov 2013 03:35, "Ron Adam" <ron3200 at gmail.com
> <mailto:ron3200 at gmail.com>> wrote:
> >
> >
> > This is one solution to what we can do to make slices both easier to
> understand and work in a much more consistent and flexible way.
> >
> > This matches the slice semantics that Guido likes.
> > (possibly for python 4.)
> >
> > The ability to pass callables along with the slice creates an easy and
> clean way to add new indexing modes. (As Nick suggested.)
>
> Tuples can't really be used for this purpose, since that's incompatible
> with multi-dimensional indexing.
>
Are there plans for pythons builtin types to use multidimensional
indexing? I don't think what I'm suggesting would create an issue with it
in either. It may even be complementary.
Either I'm missing something, or you aren't quite understanding where the
changes I'm suggesting are to be made. As long as the change is made
local to the object that uses it, it won't effect any other types uses of
slices. And what is passed in a tuple is different from specifying the
meaning of a tuple.
There may be other reasons this may not be a bad idea, but I can't think of
any myself at the moment. Possibly because a callable passed with a slice
may alter the object, but that could be limited by giving the callable a
length instead of of the object itself. But personally I like that it's
open ended and not limited by the syntax.
Consider this...
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = list([a] * 3)
>>> b
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2,
3, 4, 5, 6, 7, 8, 9]]
>>> a[2:5, 1:2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not tuple
Python lists currently don't know what to do with a tuple. In order to do
anything else, the __getitem__ and __setitem__ methods need to be
overridden. For that reason, it can't cause an issue with anything as
long as the change is kept *local to the object(s)* that use it.
Making changes at the syntax level, or even slice level could be disruptive
though. (This doesn't do that.)
>>> class Foo:
... def __getitem__(self, args):
... print(args)
...
>>> foo = Foo()
>>> foo[1,2,3,4]
(1, 2, 3, 4)
>>> foo[1:2:3, 4:5:6, 7, 8, 9]
(slice(1, 2, 3), slice(4, 5, 6), 7, 8, 9)
The slice syntax already constructs a tuple if it gets a complex set of
argument. That isn't being changed.
The only thing that it does is expand what builtin types can accept through
the existing syntax. It does not restrict, or make any change, at a level
that will prevent anything else from using that same syntax in other ways.
As a way to allow new-slices and the current slices together/overlap in a
transition period, we could just require one extra value to be passed,
which would cause a tuple to be created and the __getitem__ method could
then use the newer indexing on the slice.
s[i:j:k] # current indexing.
s[i:j:k, ''] # new indexing... Null string or None causes
tuple to be created. (or a callable that takes a slice.)
> However, I also agree containment would be a better way to go than
> subclassing.
>
> I'm currently thinking that a fourth "adjust" argument to the slice
> constructor may work, and call that from the indices method as:
>
> def adjust_indices(start, stop, step, length):
> ...
>
Currently the length adjustment is made by the __getitem__ method calling
the indices method as in this example.
>>> class Foo(list):
... def __getitem__(self, slc):
... print(slc.indices(len(self)))
...
>>> foo = Foo(range(10))
>>> foo
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> foo[:]
(0, 10, 1)
>>> foo[::-1]
(9, -1, -1) # The altered indices we don't like from the
indices method.
So you don't need to add the fourth length argument if the change is made
in __getitem__ and __setitem__.
Or possibly you can do it just in the slices, indices method.
> The values passed in would be those from the slice constructor plus the
> length passed to the indices method. The only preconditioning would be
> the check for a non-zero step.
>
> The result would be used as the result of the indices method.
>
Did you see this part of the tests?
> # And various other combinations.
>
> >>> s = Str('123456789')
>
> >>> s[3, onei] # ones indexing
> '3'
>
> >>> s[4:8, onei] # ones indexing with slice
> '4567'
>
> >>> s[4:8, onei, openi] # open interval
> '567'
>
> >>> s[4:8, onei, closedi] # closed interval
> '45678'
These all were very easy to implement, and did not require any extra logic
added to the underlying __getitem__ code other than calling the passed
functions in the tuple. It moves these cases out of the object being
sliced in a nice way. Other ways of doing it would require keywords and
logic for each case to be included in the objects.
Cheers,adjustment
Ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131104/b454433e/attachment-0001.html>
More information about the Python-ideas
mailing list