Understanding String Reversal via Slicing

Understanding string reversal via slicing

Sure, the [::] is the extended slice operator. It allows you to take substrings. Basically, it works by specifying which elements you want as [begin:end:step], and it works for all sequences. Two neat things about it:

  • You can omit one or more of the elements and it does "the right thing"
  • Negative numbers for begin, end, and step have meaning

For begin and end, if you give a negative number, it means to count from the end of the sequence. For instance, if I have a list:

l = [1,2,3]

Then l[-1] is 3, l[-2] is 2, and l[-3] is 1.

For the step argument, a negative number means to work backwards through the sequence. So for a list::

l = [1,2,3,4,5,6,7,8,9,10]

You could write l[::-1] which basically means to use a step size of -1 while reading through the list. Python will "do the right thing" when filling in the start and stop so it iterates through the list backwards and gives you [10,9,8,7,6,5,4,3,2,1].

I've given the examples with lists, but strings are just another sequence and work the same way. So a[::-1] means to build a string by joining the characters you get by walking backwards through the string.

How to explain the reverse of a sequence by slice notation a[::-1]

I think the docs are perhaps a little misleading on this, but the optional arguments of slicing if omitted are the same as using None:

>>> a = "hello"
>>> a[::-1]
'olleh'
>>> a[None:None:-1]
'olleh'

You can see that these 2 above slices are identical from the CPython bytecode:

>>> import dis
>>> dis.dis('a[::-1]') # or dis.dis('a[None:None:-1]')
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 2 (-1)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 RETURN_VALUE

For a negative step, the substituted values for None are len(a) - 1 for the start and -len(a) - 1 for the end:

>>> a[len(a)-1:-len(a)-1:-1]
'olleh'
>>> a[4:-6:-1]
'olleh'
>>> a[-1:-6:-1]
'olleh'

This may help you visualize it:

    h  e  l  l  o   
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1

How do I reverse a string in Python?

Using slicing:

>>> 'hello world'[::-1]
'dlrow olleh'

Slice notation takes the form [start:stop:step]. In this case, we omit the start and stop positions since we want the whole string. We also use step = -1, which means, "repeatedly step from right to left by 1 character".

Logic behind Python reversing a slice with index and step

It is not the case that the first number has to be less than the second, it just is the starting index, while the second is the ending index. Therefore, when you are going backwards (third index is -1), the starting index should be larger than the ending index, otherwise you'll get an empty string.

Python reverse-stride slicing

Simply exclude the end range index...

>>> foo[3::-1]
'3210'

Ironically, about the only option I think you didn't try.

slicing to reverse string confusion

In Python list indexes, the index -1 refers to the last character in the string. When using a negative step index, omitting the start index uses -1 as the start (a positive step index starts at 0 by default).

Reverse a Python string without omitting start and end slice

From the Python 2 source, this is defined with ternary expressions:

defstart = *step < 0 ? length-1 : 0;
defstop = *step < 0 ? -1 : length;

So, when start and stop are not given,

If step is negative:

  • start is length - 1
  • stop is -1, (this is the C index, tricky to implement in Python, must be -length-1)

If step is positive:

  • start is 0
  • stop is length

So to answer this question:

How would I get the result by specifying the start and end indexes?

To specify this yourself, use e.g. the following (put into a function for reusability)

def my_slice(word, step):
'''slice word with only step'''
start = len(word)-1 if step < 0 else 0
stop = -len(word)-1 if step < 0 else len(word)
return word[start:stop:step]

word = "hello"
step = -1
my_slice(word, step)

returns

'olleh'


Related Topics



Leave a reply



Submit