To understand how your current code is not working, here's a version using the same algorithm that does work. It just adds some extra steps so that you deal appropriately with the list you slice out of the main list on each call:
def reverse_string(s):
if len(s) <= 1:
return
else:
s[0], s[-1] = s[-1], s[0]
slice = s[1:-1] # slicing a list creates a new, independent list object
reverse_string(slice) # this call modifies the new list in place, leaving s unchanged
s[1:-1] = slice # so we have to assign the modified slice back to s ourselves
Note that while this does work, it's horribly inefficient, since both the slicing and the slice assignment require copying large parts of the list on each recursive call. The other answers give more efficient solutions that involve always modifying the same list, just using specific indexes rather than always swapping s[0]
and s[-1]
.
It's also worth noting that while this is how list
objects behave when you slice them, other objects in Python can act differently. A slice from a numpy
array is another array, but arrays are shallow "views" of the underlying data. Modifying a slice of an array in place often does modify the data in the array it came from too. That can be good or bad, depending on whether you expect it or not!