Reversing a String by Words or Characters

Credit: Alex Martelli

Problem

You want to reverse the characters or words in a string.

Solution

Strings are immutable, so we need to make a copy. A list is the right intermediate data structure, since it has a reverse method that does just what we want and works in place:

revchars = list(astring)       # string -> list of chars
revchars.reverse(  )           # reverse the list in place
revchars = ''.join(revchars)   # list of strings -> string

To flip words, we just work with a list of words instead of a list of characters:

revwords = astring.split(  )       # string -> list of words
revwords.reverse(  )               # reverse the list in place
revwords = ' '.join(revwords)      # list of strings -> string

Note that we use a ' ' (space) joiner for the list of words, but a '' (empty string) joiner for the list of characters.

If you need to reverse by words while preserving untouched the intermediate whitespace, regular-expression splitting can be useful:

import re
revwords = re.split(r'(\s+)', astring)     # separators too since '(...)'
revwords.reverse(  )                       # reverse the list in place
revwords = ''.join(revwords)               # list of strings -> string

Note that the joiner becomes the empty string again in this case, because the whitespace separators are kept in the revwords list by using re.split with a regular expression that includes a parenthesized group.

Discussion

The snippets in this recipe are fast, readable, and Pythonic. However, some people have an inexplicable fetish for one-liners. If you are one of those people, you need an auxiliary function (you can stick it in your built-ins from sitecustomize.py) like this:

def reverse(alist):
    temp = alist[:]
    temp.reverse(  )
    return temp

or maybe this, which is messier and slower:

def reverse_alternative(alist):
    return [alist[i-1] for i in range(len(alist), 0, -1)]

This is, indeed, in-lineable, but not worth it in my opinion.

Anyway, armed with such an almost-built-in, you can now do brave new one-liners, such as:

revchars = ''.join(reverse(list(astring)))
revwords = ' '.join(reverse(astring.split(  )))

In the end, Python does not twist your arm to make you choose the obviously right approach: Python gives you the right tools, but it’s up to you to use them.

See Also

The Library Reference section on sequence types; Perl Cookbook Recipe 1.6.

Get Python Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.