str(slice(10)) should return "slice(10)"

Currently str(slice(10)) returns "slice(None, 10, None)" If the start and step are None, consider not emitting them. Similarly slice(None) is rendered slice(None, None, None). When you're printing a lot of slices, it's a lot of extra noise.

On Thu, Oct 06, 2016 at 04:19:17PM -0700, Neil Girdhar wrote:
I have an alternative suggestion. Wouldn't it be nice if slice objects looked something like the usual slice syntax? If you think the answer is No, then you'll hate my suggestion :-) Let's keep the current repr() of slice objects as they are, using the full function-call syntax complete with all three arguments show explicitly: repr(slice(None, None, None)) => "slice(None, None, None)" But let's make str() of a slice more suggestive of actual slicing, and as a bonus, make slices easier to create too. str(slice(None, None, None)) => "slice[:]" Let the slice type itself be sliceable, as an alternate constuctor: slice[:] => returns slice(None) slice[start:] => returns slice(start, None) slice[:end] => returns slice(None, end) slice[start::step] => returns slice(start, None, step) and so forth. (This probably would require changing the type of slice to a new metaclass.) And then have str() return the compact slice syntax. At worst, the compact slice syntax is one character longer than the optimal function syntax: # proposed slice str() slice[:7] # 9 characters # proposed compact str() slice(7) # 8 characters # current str() slice(None, 7, None) # 20 characters but it will be more compact more often: slice[1:] # 9 characters versus: slice(1, None) # 14 characters slice(None, 1, None) # 20 characters -- Steve

On 12 November 2016 at 10:26, Steven D'Aprano <steve@pearwood.info> wrote:
+1, I like this idea, this is very close to what NumPy does. I would also mention http://bugs.python.org/issue24379 -- Ivan

+100 I like this idea of giving `slice` a metaclass that defines a `.__getitem__()` allowing us to construct slices on the slice type itself. FWIW, this is exactly what pandas.IndexSlice does. E.g., from http://pandas.pydata.org/pandas-docs/stable/advanced.html: In [51]: dfmi.loc[(slice('A1','A3'),slice(None), ['C1','C3']),:] In [52]: idx = pd.IndexSlice In [53]: dfmi.loc[idx[:,:,['C1','C3']],idx[:,'foo']] This is one of those nifty things that's buried in Pandas but not well documented. I'd rather spell the above simply as: dfmi.loc[slice[:,:,['C1','C3']], slice[:,'foo']] I like the change proposed to `str(slice(10))` also... and it would be way better if `slice[:10]` were actual "syntax." In fact, in that case it could even be the repr(). Note: Notwithstanding my scare quotes, Steven isn't actually asking for new syntax. "slice" is already a name, and names can already be followed by square brackets. He's just asking for a new method on a metaclass. On Sat, Nov 12, 2016 at 1:26 AM, Steven D'Aprano <steve@pearwood.info> wrote:
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Sat, Nov 12, 2016 at 9:10 PM David Mertz <mertz@gnosis.cx> wrote:
Indexing operator for classes already has a meaning, for generic types. It is a possibility that slice will become a generic type (see here: https://github.com/python/mypy/issues/2410#issuecomment-258898836) and this syntax will make it either impossible or require Slice[] to be different from slice[] in a potentially confusing way. Elazar

I thought of the use of `.__getitem__()` in metaclasses in the typing module. I feel like this use is more natural and more useful than that. Should we someday need a slice generic type for PEP 484, the spelling would naturally be `Slice[T]` instead, in my mind. But `slice[1:10,2]` should be a constructor for a concrete slice object. On Sat, Nov 12, 2016 at 11:20 AM, אלעזר <elazarg@gmail.com> wrote:
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Sat, Nov 12, 2016 at 11:41 AM, Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
Not really. We have List[T] but list[x] is invalid -- it doesn't have a different meaning (it's list instances that support indexing). And in fact the distinction between List and list is intentionally minimal -- List is simply what list wants to become when it grows up. :-) Honestly I think the use case of wanting to create a slice object is rare enough that we can continue to write slice(x, y, z). If you really find yourself wanting something shorter, I believe in the past it's been pointed out that you could create a helper, e.g. like this: class S: def __getitem__(self, x): return x s = S() a = s[:():] -- --Guido van Rossum (python.org/~guido)

The very common use case for creating slice objects is in Pandas and similar libraries. Xarray certainly, or Blaze, to a lesser extent NumPy. That said, it's very easy to define a suitable __getitem__, as Guido shows. It's really a question simply of whether that object should be named 'slice' or something else. On Nov 12, 2016 5:08 PM, "Guido van Rossum" <guido@python.org> wrote:

If we *do* want the name 'slice' as the spelling for the thing that can either be called or indexed to create a slice object, we could probably use some boilerplate like this: In [1]: class Slice: ...: def __init__(self): ...: self.slice = slice ...: def __getitem__(self, x): ...: return x ...: def __call__(self, *args, **kws): ...: return self.slice(*args, **kws) ...: In [2]: slice = Slice() In [3]: slice(1,10,2) Out[3]: slice(1, 10, 2) In [4]: slice[1:10:2] Out[4]: slice(1, 10, 2) I'm sure there are some less common uses of the name 'slice' that would break here. That's why I'd want an official standard behavior.
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Nov 12, 2016 5:46 PM, "David Mertz" <mertz@gnosis.cx> wrote:
If we *do* want the name 'slice' as the spelling for the thing that can
either be called or indexed to create a slice object, we could probably use some boilerplate like this:
break here. That's why I'd want an official standard behavior. isinstance(obj, slice) would be a notable one. -n

On Sat, Nov 12, 2016 at 5:46 PM, David Mertz <mertz@gnosis.cx> wrote:
I can't stop you from doing that in your own session, but I don't want to reuse the builtin slice object for that. If this is so useful with Pandas maybe the Pandas library can define its own helper for this purpose. -- --Guido van Rossum (python.org/~guido)

On 13 November 2016 at 04:07, Guido van Rossum <guido@python.org> wrote:
This reminds me @ vs .dot() for matrix multiplication a bit. Pandas has IndexSlicer, NumPy has index_exp, etc. I think it would be nice to have a simple common way to express this. But here we have an additional ingredient -- generic types. I think that a reasonable compromise would be to simply continue the way proposed in http://bugs.python.org/issue24379 -- just add operator.subscript for this purpose. Pros: * subscript is not a class, so that subscript[...] will be not confused with generics; * this does not require patching built-ins; * all libraries that need this will get a "common interface" in stdlib, operator module seems to be good place for this. The patch for operator.subscript was already applied, but it is now reverted because it caused a refleak. I have submitted a new patch that does not cause refleaks, I just replaced empty __slots__ with a __setattr__: it looks like __slots__ are not needed here to save memory (there is only a singleton instance), they were used just to create an immutable object. -- Ivan

On 13 November 2016 at 21:25, Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
If an actual use case is found for it, that approach would also leave "operator.subscript('EXPR')" available for a micro-eval implementation that evaluated a given string as a subscript rather than as a normal top level expression. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Sat, Nov 12, 2016 at 11:10 AM, David Mertz <mertz@gnosis.cx> wrote:
Indeed, this would be really nice! The requirement to use a special object to construct slices outside of indexing is a repeated pain-point for me and users of pandas/xarray. To non-experts, it's not at all obvious what slice(None, 3, None) means, but slice[:3] has the familiar syntax. In xarray, we encourage passing around slice objects to do indexing with keyword arguments [1], e.g., data.sel(time=slice(100)) to pull out the first 100 values along the time axis. data.sel(time=slice[:100]) would be a significant improvement. Even if we ever get indexing with keyword arguments in Python, I still like the readability of data[time=slice[:100]] better than data[time=:100], where the colon gets lost. [1] http://xarray.pydata.org/en/stable/indexing.html#indexing-with-labeled-dimen...

following all the later discussion, I'd like to come back to this initial part of this thread: An even briefer for for just "str" would be to omit the 'slice' part str(slice(None, None, None)) => "[:]" etc. Since it has colons in there, it's clear it is a slice. And it is very brief notation. -Alexander

On Thu, Oct 06, 2016 at 04:19:17PM -0700, Neil Girdhar wrote:
I have an alternative suggestion. Wouldn't it be nice if slice objects looked something like the usual slice syntax? If you think the answer is No, then you'll hate my suggestion :-) Let's keep the current repr() of slice objects as they are, using the full function-call syntax complete with all three arguments show explicitly: repr(slice(None, None, None)) => "slice(None, None, None)" But let's make str() of a slice more suggestive of actual slicing, and as a bonus, make slices easier to create too. str(slice(None, None, None)) => "slice[:]" Let the slice type itself be sliceable, as an alternate constuctor: slice[:] => returns slice(None) slice[start:] => returns slice(start, None) slice[:end] => returns slice(None, end) slice[start::step] => returns slice(start, None, step) and so forth. (This probably would require changing the type of slice to a new metaclass.) And then have str() return the compact slice syntax. At worst, the compact slice syntax is one character longer than the optimal function syntax: # proposed slice str() slice[:7] # 9 characters # proposed compact str() slice(7) # 8 characters # current str() slice(None, 7, None) # 20 characters but it will be more compact more often: slice[1:] # 9 characters versus: slice(1, None) # 14 characters slice(None, 1, None) # 20 characters -- Steve

On 12 November 2016 at 10:26, Steven D'Aprano <steve@pearwood.info> wrote:
+1, I like this idea, this is very close to what NumPy does. I would also mention http://bugs.python.org/issue24379 -- Ivan

+100 I like this idea of giving `slice` a metaclass that defines a `.__getitem__()` allowing us to construct slices on the slice type itself. FWIW, this is exactly what pandas.IndexSlice does. E.g., from http://pandas.pydata.org/pandas-docs/stable/advanced.html: In [51]: dfmi.loc[(slice('A1','A3'),slice(None), ['C1','C3']),:] In [52]: idx = pd.IndexSlice In [53]: dfmi.loc[idx[:,:,['C1','C3']],idx[:,'foo']] This is one of those nifty things that's buried in Pandas but not well documented. I'd rather spell the above simply as: dfmi.loc[slice[:,:,['C1','C3']], slice[:,'foo']] I like the change proposed to `str(slice(10))` also... and it would be way better if `slice[:10]` were actual "syntax." In fact, in that case it could even be the repr(). Note: Notwithstanding my scare quotes, Steven isn't actually asking for new syntax. "slice" is already a name, and names can already be followed by square brackets. He's just asking for a new method on a metaclass. On Sat, Nov 12, 2016 at 1:26 AM, Steven D'Aprano <steve@pearwood.info> wrote:
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Sat, Nov 12, 2016 at 9:10 PM David Mertz <mertz@gnosis.cx> wrote:
Indexing operator for classes already has a meaning, for generic types. It is a possibility that slice will become a generic type (see here: https://github.com/python/mypy/issues/2410#issuecomment-258898836) and this syntax will make it either impossible or require Slice[] to be different from slice[] in a potentially confusing way. Elazar

I thought of the use of `.__getitem__()` in metaclasses in the typing module. I feel like this use is more natural and more useful than that. Should we someday need a slice generic type for PEP 484, the spelling would naturally be `Slice[T]` instead, in my mind. But `slice[1:10,2]` should be a constructor for a concrete slice object. On Sat, Nov 12, 2016 at 11:20 AM, אלעזר <elazarg@gmail.com> wrote:
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Sat, Nov 12, 2016 at 11:41 AM, Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
Not really. We have List[T] but list[x] is invalid -- it doesn't have a different meaning (it's list instances that support indexing). And in fact the distinction between List and list is intentionally minimal -- List is simply what list wants to become when it grows up. :-) Honestly I think the use case of wanting to create a slice object is rare enough that we can continue to write slice(x, y, z). If you really find yourself wanting something shorter, I believe in the past it's been pointed out that you could create a helper, e.g. like this: class S: def __getitem__(self, x): return x s = S() a = s[:():] -- --Guido van Rossum (python.org/~guido)

The very common use case for creating slice objects is in Pandas and similar libraries. Xarray certainly, or Blaze, to a lesser extent NumPy. That said, it's very easy to define a suitable __getitem__, as Guido shows. It's really a question simply of whether that object should be named 'slice' or something else. On Nov 12, 2016 5:08 PM, "Guido van Rossum" <guido@python.org> wrote:

If we *do* want the name 'slice' as the spelling for the thing that can either be called or indexed to create a slice object, we could probably use some boilerplate like this: In [1]: class Slice: ...: def __init__(self): ...: self.slice = slice ...: def __getitem__(self, x): ...: return x ...: def __call__(self, *args, **kws): ...: return self.slice(*args, **kws) ...: In [2]: slice = Slice() In [3]: slice(1,10,2) Out[3]: slice(1, 10, 2) In [4]: slice[1:10:2] Out[4]: slice(1, 10, 2) I'm sure there are some less common uses of the name 'slice' that would break here. That's why I'd want an official standard behavior.
-- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.

On Nov 12, 2016 5:46 PM, "David Mertz" <mertz@gnosis.cx> wrote:
If we *do* want the name 'slice' as the spelling for the thing that can
either be called or indexed to create a slice object, we could probably use some boilerplate like this:
break here. That's why I'd want an official standard behavior. isinstance(obj, slice) would be a notable one. -n

On Sat, Nov 12, 2016 at 5:46 PM, David Mertz <mertz@gnosis.cx> wrote:
I can't stop you from doing that in your own session, but I don't want to reuse the builtin slice object for that. If this is so useful with Pandas maybe the Pandas library can define its own helper for this purpose. -- --Guido van Rossum (python.org/~guido)

On 13 November 2016 at 04:07, Guido van Rossum <guido@python.org> wrote:
This reminds me @ vs .dot() for matrix multiplication a bit. Pandas has IndexSlicer, NumPy has index_exp, etc. I think it would be nice to have a simple common way to express this. But here we have an additional ingredient -- generic types. I think that a reasonable compromise would be to simply continue the way proposed in http://bugs.python.org/issue24379 -- just add operator.subscript for this purpose. Pros: * subscript is not a class, so that subscript[...] will be not confused with generics; * this does not require patching built-ins; * all libraries that need this will get a "common interface" in stdlib, operator module seems to be good place for this. The patch for operator.subscript was already applied, but it is now reverted because it caused a refleak. I have submitted a new patch that does not cause refleaks, I just replaced empty __slots__ with a __setattr__: it looks like __slots__ are not needed here to save memory (there is only a singleton instance), they were used just to create an immutable object. -- Ivan

On 13 November 2016 at 21:25, Ivan Levkivskyi <levkivskyi@gmail.com> wrote:
If an actual use case is found for it, that approach would also leave "operator.subscript('EXPR')" available for a micro-eval implementation that evaluated a given string as a subscript rather than as a normal top level expression. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Sat, Nov 12, 2016 at 11:10 AM, David Mertz <mertz@gnosis.cx> wrote:
Indeed, this would be really nice! The requirement to use a special object to construct slices outside of indexing is a repeated pain-point for me and users of pandas/xarray. To non-experts, it's not at all obvious what slice(None, 3, None) means, but slice[:3] has the familiar syntax. In xarray, we encourage passing around slice objects to do indexing with keyword arguments [1], e.g., data.sel(time=slice(100)) to pull out the first 100 values along the time axis. data.sel(time=slice[:100]) would be a significant improvement. Even if we ever get indexing with keyword arguments in Python, I still like the readability of data[time=slice[:100]] better than data[time=:100], where the colon gets lost. [1] http://xarray.pydata.org/en/stable/indexing.html#indexing-with-labeled-dimen...

following all the later discussion, I'd like to come back to this initial part of this thread: An even briefer for for just "str" would be to omit the 'slice' part str(slice(None, None, None)) => "[:]" etc. Since it has colons in there, it's clear it is a slice. And it is very brief notation. -Alexander
participants (10)
-
Alexander Heger
-
David Mertz
-
Guido van Rossum
-
Ivan Levkivskyi
-
Nathaniel Smith
-
Neil Girdhar
-
Nick Coghlan
-
Stephan Hoyer
-
Steven D'Aprano
-
אלעזר