Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #11924 > unrolled thread

Re: extended slicing and negative stop value problem

Started byChris Angelico <rosuav@gmail.com>
First post2011-08-20 19:29 +0100
Last post2011-08-21 15:16 -0700
Articles 6 — 4 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: extended slicing and negative stop value problem Chris Angelico <rosuav@gmail.com> - 2011-08-20 19:29 +0100
    Re: extended slicing and negative stop value problem Max <maxmoroz@gmail.com> - 2011-08-20 11:52 -0700
      Re: extended slicing and negative stop value problem Chris Angelico <rosuav@gmail.com> - 2011-08-20 20:53 +0100
    Re: extended slicing and negative stop value problem Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-08-21 06:40 +1000
      Re: extended slicing and negative stop value problem Max <maxmoroz@gmail.com> - 2011-08-21 10:27 -0700
        Re: extended slicing and negative stop value problem Chris Rebert <clp2@rebertia.com> - 2011-08-21 15:16 -0700

#11924 — Re: extended slicing and negative stop value problem

FromChris Angelico <rosuav@gmail.com>
Date2011-08-20 19:29 +0100
SubjectRe: extended slicing and negative stop value problem
Message-ID<mailman.270.1313864985.27778.python-list@python.org>
On Sat, Aug 20, 2011 at 7:20 PM, Max Moroz <maxmoroz@gmail.com> wrote:
> Would it be a good idea to change Python definition so that a[10, -1, -1]
> referred to the elements starting with position 10, going down to the
> beginning?

Well, first off I think it's a dangerous idea to change semantics of
something like that. I can see your use case, but I think that what
you want is covered by simply omitting the stop marker:

>>> a="qwertyuiopasdfghjklzxcvbnm"
>>> a[10:1:-1]
'apoiuytre'
>>> a[10:0:-1]
'apoiuytrew'
>>> a[10::-1]
'apoiuytrewq'

If you're using a variable for the stop value, you just need to set it
to an explicit None if it would fall negative:

>>> a[10:None:-1]
'apoiuytrewq'

Hope that helps!

ChrisA

[toc] | [next] | [standalone]


#11927

FromMax <maxmoroz@gmail.com>
Date2011-08-20 11:52 -0700
Message-ID<9c3643a8-ba91-4b0b-8144-f4a6260d6cf0@j14g2000prh.googlegroups.com>
In reply to#11924
On Aug 20, 11:29 am, Chris Angelico <ros...@gmail.com> wrote:
> If you're using a variable for the stop value, you just need to set it
> to an explicit None if it would fall negative:
>
> >>> a[10:None:-1]
>

That doesn't work if it's set in a loop or if it's calculated as a
formula. For example, this very simple code doesn't work because of
the "-1 problem".

# find the longest substring that reads the same left to right and
right to left
for substr_length in range(len(input),0,-1):
    for starting_pos in range(len(input)-substr_length+1):
        ending_pos = starting_pos + substr_length - 1
        if input[starting_pos:ending_pos+1] == input[ending_pos :
starting_pos-1 : -1]:
           print(input[starting_pos:ending_pos+1])
           exit(0)

Of course you can rewrite it, but it becomes quite ugly.

(Not to mention, people who learn the language would not always know
this, and will end up with a bug.)

[toc] | [prev] | [next] | [standalone]


#11928

FromChris Angelico <rosuav@gmail.com>
Date2011-08-20 20:53 +0100
Message-ID<mailman.271.1313870035.27778.python-list@python.org>
In reply to#11927
On Sat, Aug 20, 2011 at 7:52 PM, Max <maxmoroz@gmail.com> wrote:
> That doesn't work if it's set in a loop or if it's calculated as a
> formula. For example, this very simple code doesn't work because of
> the "-1 problem".
>

Right, which is what I meant by setting it to an explicit None:

if input[starting_pos:ending_pos+1] == input[ending_pos :
starting_pos-1 if starting_pos >= 0 else None : -1]:

You're right that it starts to get ugly, though.

Of course, there are other ways to find the longest palindromic
substring in a string:

# I wouldn't bother counting a one-character "palindrome"
for substr_length in range(len(input),1,-1):
   for starting_pos in range(len(input)-substr_length+1):
       ending_pos = starting_pos + substr_length - 1
       testme = input[starting_pos:ending_pos+1]
       if testme == testme[::-1]:
          print(testme)
          exit(0)

That is, snip out the string and then reverse that snipped piece,
rather than reverse-slicing from the original. This doesn't solve the
issue of slicing backwards with variable halts, though.

ChrisA

[toc] | [prev] | [next] | [standalone]


#11931

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-08-21 06:40 +1000
Message-ID<4e501ba1$0$29970$c3e8da3$5496439d@news.astraweb.com>
In reply to#11924
Pardon me for breaking threading, but I don't have Max's original post.

On Sat, Aug 20, 2011 at 7:20 PM, Max Moroz <maxmoroz@gmail.com> wrote:

> Would it be a good idea to change Python definition so that a[10, -1, -1]

I presume you mean slice notation a[10:-1:-1].


> referred to the elements starting with position 10, going down to the
> beginning?

No, almost certainly not. Such a change would break backwards compatibility,
and so would only be allowed under very unusual circumstances: the current
behaviour would have to be a major problem, or the new behaviour a huge
benefit, or both, to make up for:

(1) the extra work needed to change the behaviour (probably involving
a "from __future__ import ..." feature for the first version or two); 

(2) breaking people's existing code; and

(3) forcing people to learn the new behaviour and unlearn the old.

Even if the old behaviour is "wrong", the work needed to fix it may be more
than the benefit. If this was going to be "fixed", the time was probably
about three years ago, when Python3 was just starting. Now such a change
will probably need to wait for the hypothetical Python 4000.

 
> This would require disabling the "negative stop value means counting from
> the end of the array" magic whenever the step value is negative.

Which will hurt people who expect the current behaviour:

>>> a[8:-8:-1]
[8, 7, 6, 5, 4, 3]


> The reason for this idea is that many people (me including) try to use
> extended slices with negative step values, only to realize that they are
> messed up. For example, if your stop value is reduced in a loop from a
> positive number to -1, the behavior breaks whenever it hits -1.

Yes, negative step values are unintuitive, especially if the step is not -1.
The solution is, "Don't do that then!". 

The usual advice is to do your slicing twice, reversing it the second time:


a[0:11][::-1]
# Instead of a[10:-1:-1], which looks like it should work, but doesn't.

(or use the reversed() built-in instead of the second slice), or to write a
helper function to adjust the indexes and get whatever behaviour you like.
Hint:

>>> a[10:-11:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#11947

FromMax <maxmoroz@gmail.com>
Date2011-08-21 10:27 -0700
Message-ID<7488461a-de1f-4e7c-ba7f-a15d85896e08@y39g2000prd.googlegroups.com>
In reply to#11931
On Aug 20, 1:40 pm, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> Pardon me for breaking threading, but I don't have Max's original post.

Not sure why; I also can't see it! I'll copy it at the end just in
case.

> On Sat, Aug 20, 2011 at 7:20 PM, Max Moroz <maxmo...@gmail.com> wrote:
> > Would it be a good idea to change Python definition so that a[10, -1, -1]
>
> I presume you mean slice notation a[10:-1:-1].
>
> > referred to the elements starting with position 10, going down to the
> > beginning?
>
> If this was going to be "fixed", the time was probably
> about three years ago, when Python3 was just starting. Now such a change
> will probably need to wait for the hypothetical Python 4000.

Yeah, I was surprised that it didn't bother anyone..

> The usual advice is to do your slicing twice, reversing it the second time:
>
> a[0:11][::-1]
> # Instead of a[10:-1:-1], which looks like it should work, but doesn't.

It works nicely, but it is 1.3 times slower in my code (I am surprised
the interpreter doesn't optimize this).

[toc] | [prev] | [next] | [standalone]


#11966

FromChris Rebert <clp2@rebertia.com>
Date2011-08-21 15:16 -0700
Message-ID<mailman.289.1313964991.27778.python-list@python.org>
In reply to#11947
On Sun, Aug 21, 2011 at 10:27 AM, Max <maxmoroz@gmail.com> wrote:
> On Aug 20, 1:40 pm, Steven D'Aprano <steve
> +comp.lang.pyt...@pearwood.info> wrote:
>> On Sat, Aug 20, 2011 at 7:20 PM, Max Moroz <maxmo...@gmail.com> wrote:
>> > Would it be a good idea to change Python definition so that a[10, -1, -1]
>>
>> I presume you mean slice notation a[10:-1:-1].
>>
>> > referred to the elements starting with position 10, going down to the
>> > beginning?
<snip>
>> The usual advice is to do your slicing twice, reversing it the second time:
>>
>> a[0:11][::-1]
>> # Instead of a[10:-1:-1], which looks like it should work, but doesn't.
>
> It works nicely, but it is 1.3 times slower in my code (I am surprised
> the interpreter doesn't optimize this).

That would require CPython to assume certain slicing semantics for all
types (which it can't) or to check for this very specific case at
runtime (which would slow down all other [list] slicing operations).

A smarter implementation such as PyPy could indeed theoretically
optimize this case though.

Cheers,
Chris

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web