How to Reverse a String in Python
How to Reverse a String in Python
Oct 13, 2021
Computer Science - Other

How to Reverse a String in Python

In Python, strings are iterable and there is no included function to reverse a string. One rationale for excluding a string.reverse() method is to give Python developers an incentive to leverage the power of this special circumstance. Each character in a string may be easily handled as part of a sequence of elements, much like arrays in other languages.

So, how would you reverse a string in Python?

The Quick Answer

The quickest way to reverse a string in Python is to use a slice that steps by -1:

'Test string'[::-1]

In Python, the str object does not include a built-in reverse function.

If you’re teaching yourself to code, here are a couple things about Python's strings that you should be aware of:

  • In Python, strings are immutable; they can’t be changed. This is so that users can't inadvertently modify the object's content, which helps to avoid errors. Integer, float, tuple, and bool are a few of the other immutable objects in Python.
  • Strings may be sliced. A string may be sliced to create a new string starting at one point and proceeding backward or forward by a certain distance. They can be formed with either slice notation or by creating a slicing object.

Slice notation is simple once you wrap your head around it. The subscript in ‘Test string’[subscript] creates a slice when a colon is included in the square brackets:

It follows the format below:

string[start:stop:step]

The start segment specifies the starting integer where the slicing will begin. It simply defaults to None if nothing is specified, corresponding to starting at the first element. Similarly, if no stop command is specified, the slicing will default to None, corresponding to ending at the last element. The step will default to None, corresponding to a step size of 1.

Here, we have only specified -1 as the step. A negative value will make the slicing reverse through the sequence. -1 will go through every item in the sequence backward, and -2 would go through every second item in the sequence backward.

For example let’s use slice notation and see what the console output becomes:

print('Test string'[1::])

Here the output starts at index value of 1.

Output: est string

Now, let’s change the start value to negative.

print('Test string'[-1::])

With a negative start, we start at the last index value minus one and get the following:

Output: g

Let’s change the stop value to 1.

print('Test string'[:1:])

With a stop value of 1, the output stops after the first character:

Output: T

Let’s change the stop value to negative.

print('Test string'[:-1:])

With a stop value of negative 1, the output stops at one less the maximum index value of the string:

Output: Test string

With the step value set to positive 1, we receive a copy of the string.

print('Test string'[::1])

Output: Test string

It follows that when we set the step value to negative 1, we receive a copy of the string, but reversed.

print('Test string'[::-1])

Output: gnirts tseT

To improve readability, it’s recommended that you put this in a function

def reverse_string(string):

    return string[::-1]

This way, you can call this function later in your code as many times as needed. For example, to print a reversed string to the console you would use the following code:

print(reverse_string(‘Test string’))

The console readout would be:

gnirts tseT

For reference, here is the code all together:

def reverse_string(string):

    return string[::-1]

print(reverse_string('Test string'))

If you need to create a slice outside of the square brackets, then you'll need to create a slice object and specify None where applicable:

slice_object = slice(None,None,-1)

print('Test string'[slice_object])

Slice objects can be reused multiple times and their values can be changed. They could come in handy depending on what the desired outcome of your code is!

The Alternate Quick Answer

Alternatively, you can call the join() method with the reversed() function, which takes all elements in an iterable object and combines them into one string while reversing them.

def reverse_string(string):

    return ''.join(reversed(string))

print(reverse_string('Test string'))

The console output:

gnirts tseT

The '' in the code below simply indicates what separator is used when joining the strings. If you use the following code:

def reverse_string(string):

    return '!'.join(reversed(string))

print(reverse_string('Test string'))

You’ll receive the following reversed output instead:

g!n!i!r!t!s! !t!s!e!T

The Alternate No Slice Answer

Slice notation in Python might be difficult to comprehend for some users and developers who do not wish to put in a lot of effort.

However, once the fundamental concepts are understood, this technique's dominance over fixed-string manipulation techniques may be quite significant.

If you're not sure what alternatives are available, don't worry; there are a variety of strategies to reverse strings in Python. Lambda functions, iterators, and simple one-off function declarations are just a few examples. Developers may also construct their own string.reverse() function, although understanding the many aspects of this programming language can be beneficial.

Here is a simple for loop in a function to reverse a string in Python that starts with declaring your variables:

def reverse_string(string):

    reversed_string = ""

    for x in string:

        reversed_string = x+reversed_string

    return(reversed_string)

print(reverse_string('Test string'))

The output is the same reversed string as before:

gnirts tseT

What’s happening is that the for loop is iterating through every character in “Test string.”

After the first loop we have the first character “T”:

reversed_string =T+””

And then reversed_string is set to T, after the second pass we have the second character in “Test string”, which is “e”:

reversed_string =e+T

Thus, reversed_string is set to eT, and after the second pass through the for loop we have:

reversed_string =s+eT

So reversed_string is set to seT, and so on.

The ‘Best Practices’ Answer

To employ programming best practices, it’s best to start with an empty string and create a new string from the old one. This task can be accomplished by using pure syntax and literals inside a while loop:

def reverse_string(string):

    reversed_string = ''

    index = len(string)

    while index:

        index -= 1                                   

        reversed_string += string[index]             

    return reversed_string

print(reverse_string('Test string'))

Your console output will be:

gnirts tseT

However, this method has a downside of its own because, remember, in Python, strings are immutable. This means that in each situation where it appears as if you're appending a character to your new_string, Python is actually creating a new string. However, in certain circumstances such as these, Python knows how to optimize this so the processing time won’t increase with many repetitions and large computations.

Let’s break down the functions in this code sample.

  • In the first line, reversed_string = '' we’re simply declaring reversed_string as an empty string.
  • The next line is index = len(string), here we are declaring a variable called index to be equal to the number of items in the object by calling the len() function on the string which is passed through the function. This example is 11 characters long so len(string) = 11.
  • while index: This means to loop continuously as long as the expression evaluates as true, in this case, as long as the index has elements in it.
  • index -= 1 This is reducing the index value by 1 with each iteration; this will let the while loop continue for 11 iterations.
  • reversed_string += string[index]This shows you how to use the += operator, which performs a straightforward sum and assignment. The two values are combined with the plus sign and assigned to the variable on the left of the operator. This sets the reversed_string as the index value of 10 in the string passed to the function. Remember that in Python, strings are 0-indexed, so the first element starts at 0 as per the following table.

 

Element

T

e

s

t

 

s

t

r

i

n

g

Index Value

0

1

2

3

4

5

6

7

8

9

10

 

  • For the first iteration, reversed_string is set to g, then the next indexed character is added to the string, so it is set to gn for the next iteration, then gni and so on. When the while loop exits, reversed_string is returned.

Theoretically, it would be even better to collect all the newly created strings in a list, and use the join() method on them later to avoid creating a new string every time with the following:

def reverse_string(string):

    created_strings = []

    index = len(string)

    while index:

        index -= 1                      

        created_strings.append(string[index])

    return ''.join(created_strings)

print(reverse_string('Test string'))

This makes use of the append() method, which adds a new element to the end of the list instead of using the operator +=.

The Emoji Answer

So far, all the methods above are correct only if Unicode Modifiers and grapheme clusters are ignored. For example, the following emojis have multiple modifiers πŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘Ά (Family: Man, Woman, Boy, Baby) and πŸ‘¨‍πŸ‘¨‍πŸ‘¦ (Family: Man, Man, Boy).

Let’s try to reverse the following string: πŸ‘¨‍πŸ‘¨‍πŸ‘¦πŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘Ά

If you use the above methods you’ll get the below console output:

πŸ‘¦‍πŸ‘¨‍πŸ‘¨πŸ‘Ά‍πŸ‘¦‍πŸ‘©‍πŸ‘¨

This is a string of a Boy, Man and Man, Baby, Boy, Woman and Man, the modifiers were reversed resulting in the graphemes becoming separated.

There is a package to correctly handle graphemes. It can be installed via the command line with pip installer. In Python 3.9.7 the command to install the grapheme package is:

py -m pip install grapheme

If this doesn’t work for you, try to update pip with:

py -m pip install --upgrade pip setuptools wheel

The Python code to correctly reverse strings with emojis requires the grapheme package, and the process is much the same as before:

import grapheme

def reverse_emojis(string):

    g = list(grapheme.graphemes(string))

    return ''.join(g[::-1])

print(reverse_emojis("πŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘ΆπŸ‘¨‍πŸ‘¨‍πŸ‘¦"))

The printed console output with this function will be:

πŸ‘¨‍πŸ‘¨‍πŸ‘¦πŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘Ά

This answer performs the slowest out of all the presented solutions so far. It might be simpler and faster to just throw an error if the inputted string contains an emoji. In the command line, be sure to install the emoji and regex packages to determine if the string contains an emoji:

py -m pip install emoji

py -m pip install regex

Then we can create a function that can test if any character in the string contains an emoji with the below code:

import emoji

import regex

def contains_emoji(string):

    emoji_list = []

    data = regex.findall(r'\X', string)

    for string in data:

        if any(char in emoji.UNICODE_EMOJI['en'] for char in string):

            emoji_list.append(string)

    if len(emoji_list)>0:

        return(bool(True))

    else:

        return(bool(False))

We would have to add this check for the other operations to ensure that graphemes and emojis are handled correctly when reversed. We can run the string through this check, and if it contains an emoji we would perform the grapheme reversal, and if it did not we would perform one of the other faster solutions to optimize processing speed. Here is the complete solution:

import emoji

import regex

string = "Test string πŸŒΌπŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘Ά" #This is the test string

def reverse_string(string): #Using reversal method from “The Alternate No Slice Answer”

    reversed_string = ""

    for x in string:

        reversed_string = x+reversed_string

    return(reversed_string)

def contains_emoji(string):

    emoji_list = []

    data = regex.findall(r'\X', string)

    for string in data:

        if any(char in emoji.UNICODE_EMOJI['en'] for char in string):

            emoji_list.append(string)

    return(len(emoji_list))

if contains_emoji(string)==0:

    print(reverse_string(string))

    print("Does not contain emojis.")

else:

    print(reverse_emojis(string))

    print("Contains emojis.")

The console output is as follows:

πŸ‘¨‍πŸ‘©‍πŸ‘¦‍πŸ‘ΆπŸŒΌ gnirts tseT

Contains emojis.

And if we change the test string value to a string that does not contain emojis:

string = "Test string"

Then we receive the below console output:

gnirts tseT

Does not contain emojis.

This final method is the most robust and would offer fast processing speed with a great number of randomly generated iterations. Typically, emojis are restricted characters for most usages so this level of care is normally not required for working models for reversing a string in Python. With more extensive tests, The Alternate No Slice Answer seemed to perform the fastest.

View Available Computer Science Tutors