In looking at some python strings and functions, I discovered this strange quirk of python:
s = "hello"
print s[::-1]
which then prints: olleh
However, print s[len(s)-1:-1:-1] doesn't work. My understanding is that it should iterate from the last element s[len(s)-1] to the first element s[0]. However, it just prints an empty string '', which I believe is because in strings of some given length (say, 5), s[4] == s[-1]. But, I don't understand why python decides to use -1 instead of 4, which is the actual len(s).
Furthermore, s[len(s):0:-1] + s[0] works. Why is len(s) a valid index? Does python just convert len(s) to 0 arbitrarily?
P.S. This is in Python 2.7.8, I'm not sure if it also works in 3.x.x
EDIT: Confirmed to be the same in Python 3
The slice notation is this:
s[start:stop:step]
specifically, stop being up to but not including it. Translate this to what you're asking:
s[len(s)-1:-1:-1]
This is, based on the length of 5 for 'hello'
s[4:-1:-1]
or
s[4:4:-1]
which is an empty, or zero-length string.
I have given a much more in-depth exposition of the slice notation here: Explain Python's slice notation
Negative indexes are counted from the end of the sequence, so you're just getting [-1:-1:-1], or equivalently [4:4:-1] which is zero-length string.
Remember that indexes start at 0, not 1.
[len(s)-1] gets the last letter ('o')
:-1 is just 'o' again, because you're getting the last value.
So then you want to go from the last value... to the last value... reversed (-1). Of course that will return an empty string.
To answer your second question, that's because no errors are ever raised when using index notation. Try doing print s[32489375:2784:-123]
You are mapping backwards using a step of negative one. The default is:
from 0 to len(collection) by step
When you use a negative step the indices need to be reversed as well, or else you'll go the long way round. For example, from 0 to 5 by -1 goes: 0 + -1 = -1; -1 + -1 = -2 ... some time later an integer overflows ...)
In order to avoid this long walk around Python reverses the indices when step is negative and treats it as:
from len(collection) to 0 by step
This means that you need to deal with the start and end values in this case as negative integers from len(collection) - so, if you want to get the entire string in reverse, you are looking for:
s[-1:-(len(s) + 1):-1]
Or, in simpler terms:
from {the last item in the collection} to {the first item in the collection} by -1
This answer also has a good visual explanation for the indices.
Related
I have a variabel s="Siva"
and I have tried doing slicing using a logic
s[0:-5:-1]
According to the concept of slicing I am going in the backward direction, so it should ideally start from "S" and then go to "a","v","i" However when i tried running this I am getting an output as only "S" and even when I tried using s[0:-100:-1] it is still showing "S". Can anyone explain why this is happening?
The step count given by you in s[0:-5:-1] is -1, which means that string slicing will be reverse like 'a','v','i','S'.
But you are starting from s[0] which is "S" and due to the step count -1,it will print the previous character from the string "Siva",But there are no characters before 'S'.That's why it's stopping and only printing 'S'.
If you want the reverse of s = "Siva",
then simply write s[::-1].
Slicing is s[start:end:step] so if you want Savi you have to do
s[0] + s[-1:0:-1]
Start at -1 means start at the end of the string.
End at 0 means end at the beginning ignoring this first character.
Step -1 means go reverse one at a time.
Indeed, slicing accepts [start:stop:step] in its syntax. What you're saying with [0, -5, -1] is "start at index 0; advance until index -4 (inclusive); and do so with steps of -1".
Your string is of length 4 and so index -4 is actually index 0: s[-4] would be 'S'.
In other words, you're basically saying: "start at index 0 and finish at index 0 (inclusive)", which is why you get only 'S'. Anything smaller than -5, for instance: -10, would also give you 'S' only because there's nowhere further to go: it's essentially the same as what would happen if you tried to do s[0:100000:1]: you'd simply get 'Siva', because your string is 4<100000 characters long, and Python's behaviour in such cases is to just return all four (or, more generally: return as many characters as it can in "the direction of iteration", based on the sign of your step parameter, before reaching the end of the string).
On the other hand, if you try something that is greater than -5, such as, say, -2 or even just a positive 3, you'd get an empty string: that's because you'd basically be saying "start at index -4 and advance in the negative direction until you reach something greater" – this is never expected to happen and is somewhat "gibberishy" in nature, and I guess the way Python chose to deal with it is to just return an empty string in those cases.
This was intended to answer your question of "why this happens" while granting some intuition, hopefully; when it comes to a solution, if what you want is to simply grab the first letter and then reverse the rest: I'd simply use s[0] + s[-1:0:-1]. For fun I'll note that another option would be s[0] + s[1:][::-1].
Slicing is used with [start:stop:step]. If you use negative numbers for start it will start at the specified index, from the end.
If you want to print "Savi", I think you must have to slices :
s="Siva"
s[0] + s[-1::-1]
Perhaps what you expected couldn't be done with a string slice, but could still be done with indexing.
>>> ''.join(s[i] for i in range(0,-5,-1))
'SaviS'
This question already has answers here:
Understanding slicing
(38 answers)
Closed 6 years ago.
I'm trying to understand the logic behind reversing a slice using slice index and step.
First of all, I can reverse a string using the slice step like this:
a = "Hello"
a[::-1]
>>> 'olleH'
Also, I can reverse only a part of the string like this:
a = "Hello"
a[:2:-1]
>>> 'ol'
But when I try to reverse the string using another range like this:
a = "Hello"
a[1:3:-1]
>>> ''
I get an empty string.
However, if I inverse the ranges like this example:
a = "Hello"
a[4:1:-1]
>>> 'oll'
I get the reversed slice between indexes 1 and 4.
But, correct me if I'm wrong, I know that the first index from a slice must be less than the second index.
This is why when I run this example:
a = "Hello"
a[4:1]
>>> ''
I get an empty string.
So, can somebody explain to me why reversing a string (slice) while an inversed range with a negative step works, and using the logic of the first index being less than the second one in a slice will give an empty string.
Thanks for your answers.
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.
The syntax is
a[begin;end;step]
So when you use step -1 it will traverse through the string backwards and thus begin should be bigger than the end.
If you omit step it defaults to 1 and will traverse through the string forward and should begin must be smaller than the end.
Fun fact, you can also traverse in steps of -2
a = 'Hello, world!'
a[::-2] # => '!lo olH'
This question already has answers here:
Understanding slicing
(38 answers)
Closed 4 years ago.
I cannot understand this. I have seen this in people's code. But cannot figure out what it does. This is in Python.
str(int(a[::-1]))
Assuming a is a string. The Slice notation in python has the syntax -
list[<start>:<stop>:<step>]
So, when you do a[::-1], it starts from the end towards the first taking each element. So it reverses a. This is applicable for lists/tuples as well.
Example -
>>> a = '1234'
>>> a[::-1]
'4321'
Then you convert it to int and then back to string (Though not sure why you do that) , that just gives you back the string.
The notation that is used in
a[::-1]
means that for a given string/list/tuple, you can slice the said object using the format
<object_name>[<start_index>, <stop_index>, <step>]
This means that the object is going to slice every "step" index from the given start index, till the stop index (excluding the stop index) and return it to you.
In case the start index or stop index is missing, it takes up the default value as the start index and stop index of the given string/list/tuple. If the step is left blank, then it takes the default value of 1 i.e it goes through each index.
So,
a = '1234'
print a[::2]
would print
13
Now the indexing here and also the step count, support negative numbers. So, if you give a -1 index, it translates to len(a)-1 index. And if you give -x as the step count, then it would step every x'th value from the start index, till the stop index in the reverse direction. For example
a = '1234'
print a[3:0:-1]
This would return
432
Note, that it doesn't return 4321 because, the stop index is not included.
Now in your case,
str(int(a[::-1]))
would just reverse a given integer, that is stored in a string, and then convert it back to a string
i.e "1234" -> "4321" -> 4321 -> "4321"
If what you are trying to do is just reverse the given string, then simply a[::-1] would work .
Why does [:-0] return an empty string? There is a variable in my code which determines a length of string which have to be cut. The problem is that it returns empty string when there is int(0) in this variable.
Example:
def rightPass(word,value):
substring = word[:-value]
return substring
for i in range(3,-1,-1):
print rightPass('word',i)
>>> w
>>> wo
>>> wor
>>>
I do know that it is not a big deal to do this:
def rightPass(word,value):
substring = word[:-value] if value!=0 else word
return substring
But I can't find a reason why is [:-0] acting this way.
I though that it is because Python doesn't know -0 value but I tried it using 0 and the same problem occurred.
Can somebody explain it?
You are asking Python to create a new string from index 0 to index 0. And that's an empty slice.
The end value of a slice is exclusive. Python picks all characters from the starting index that come before the end index. Here -0 is the same thing as 0 (negative zero is the same thing as positive zero).
Note that that is different from using actual negative values; [0:-1] would take the length and replace the negative value with len(object) - 1 and use that as the end value, but this doesn't work for -0, because that is not a negative value!
You can use None instead of 0 if you wanted to slice to the end:
substring = word[:-value if value else None]
The second parameter in the slice is the end position.
[start : stop : step]
And the range of start to stop is half open, meaning it includes start up to but not including stop.
So [: 0] means start at [0] and stop at but don't include [0], which can only be empty string.
To my knowledge, indexing with -1 will bring you up the last item in a list e.g.
list = 'ABCDEFG'
list[-1]
'G'
But when you are asking for a sequence from the list, -1 gives the second to last term in a list,
list[3:-1]
'DEF'
Why? I would have expected, and would like to get DEFG
It is because the stop (second) argument of slice notation is exclusive, not inclusive. So, [3:-1] is telling Python to get everything from index 3 up to, but not including, index -1.
To get what you want, use [3:]:
>>> list = 'ABCDEFG'
>>> list[3:]
'DEFG'
>>>
>>> list[3:len(list)] # This is equivalent to doing: list[3:]
'DEFG'
>>>
Also, just a note for the future: it is considered a bad practice to use list as a variable name. Doing so overshadows the built-in.
It's for the same reason that list[3:4] doesn't include the character at the 4th index; slicing is not inclusive. In addition, you can slice from a character to the end simply by omitting the second slice parameter, as in list[3:].