Ogen
Ogen

Reputation: 6709

Reverse a Python string without omitting start and end slice

How do you reverse a Python string without omitting the start and end slice arguments?

word = "hello"
reversed_word = word[::-1]

I understand that this works, but how would I get the result by specifying the start and end indexes?

word = "hello"
reversed_word = word[?:?:-1]

It's hard to explain to students why word[::-1] reverses a string. It's better if I can give them logical reasoning rather than "it's the pythonic way".

The way I explain word[::1] is as follows: "You have not specified the start so it just starts from the start. You have not specified the end so it just goes until the end. Now the step is 1 so it just goes from the start to the end 1 character by 1." Now when my students see word[::-1] they are going to think "We have not specified the start or the end so it will go through the string -1 characters at a time?"

Upvotes: 21

Views: 3056

Answers (7)

haccks
haccks

Reputation: 105992

Some other ways to reverse a string:

word = "hello"
reversed_word1 = word[-1: :-1] 
reversed_word2 = word[len(word)-1: :-1]   
reversed_word3 = word[:-len(word)-1 :-1]    

One thing you should note about the slicing notation a[i:j:k] is that omitting i and j doesn't always mean that i will become 0 and j will become len(s). It depends upon the sign of k. By default k is +1.

  • If k is +ve then the default value of i is 0 (start from the beginning). If it is -ve then the default value of i is -1 (start from the end).
  • If k is +ve then the default value of j is len(s) (stop at the end). If it is -ve then the default value of j is -(len(s)+1) (stop at the beginning).

Now you can explain your students how Hello[::-1] prints olleH.

Upvotes: 15

Aaron Hall
Aaron Hall

Reputation: 394825

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'

Upvotes: 4

Sumurai8
Sumurai8

Reputation: 20737

The notation string[begin:end:increment] can be described with the following Python program:

def myreverse( string, begin, end, increment ):
  newstring = ""
  if begin >= 0 and end < 0:
    begin = -1
  for i in xrange(begin, end, increment):
    try:
      newstring += string[i]
    except IndexError:
      pass

  return newstring

Upvotes: 2

jkd
jkd

Reputation: 1045

Not quite sure why, but the following will return the reverse of word:

word = "hello"
word[len(word):-(len(word)+1):-1]

Or...

word = "hello"
word[len(word):-len(word)-1:-1]

Edit (Explanation):

From jedward's comment:

The middle parameter is the trickiest, but it's pretty straightforward once you realize (a) negative indices to slice start/stop indicate that you want to count "backwards" from the end of the string, and (b) the stop index is exclusive, so it will "count" up to but stop at/before the stop index. word[len(word):-len(word)-1:-1] is probably more clear.

In response to this comment:

The third value is actually the increment so you are telling Python that you want to start at the last letter then return all the (-1)st values up to the last one.

Here is an drawing (pulled together in a minute): enter image description here

The drawing shows that we can also use this instead:

word = "hello"
word[-1:-len(word)-1:-1] #-1 as the first

Upvotes: 13

Akavall
Akavall

Reputation: 86128

In [27]: word
Out[27]: 'hello'

In [28]: word[-1:-6:-1]
Out[28]: 'olleh'

Why this works:

In [46]: word
Out[46]: 'hello' 

In [47]: word[-1] # you want o to be your first value
Out[47]: 'o'

In [48]: word[-5] # you want h to be your last value
Out[48]: 'h'

In [49]: word[-1:-6:-1] # therefore ending point should be one
Out[49]: 'olleh'        # past your last value that is -6  

Upvotes: 3

user2555451
user2555451

Reputation:

If you do not specify a number for slice notation, Python will use None as a default. So, you can just explicitly write the None values:

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

Upvotes: 4

Prashant G
Prashant G

Reputation: 4900

Recursive approach:

def reverse(word):
    if len(word) <= 1:
        return word

    return reverse(word[1:]) + word[0]

Upvotes: 1

Related Questions