Comparing Strings using Python

In Python, strings are sequences of characters, which are effectively stored in memory as an object. Each object can be identified using the id() method, as you can see below. Python tries to re-use objects in memory that have the same value, which also makes comparing objects very fast in Python:

$ python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)  
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.  
>>> a = "abc"
>>> b = "abc"
>>> c = "def"
>>> print (id(a), id(b), id(c))
(139949123041320, 139949123041320, 139949122390576)
>>> quit()

In order to compare strings, Python offers a few different operators to do so. First, we will explain them in more detail below. Second, we'll go over both the string and the re modules, which contain methods to handle case-insensitive and inexact matches. Third, to deal with multi-line strings the difflib module is quite handy. A number of examples will help you to understand how to use them.

The == and != Operators

As a basic comparison operator you'll want to use == and !=. They work in exactly the same way as with integer and float values. The == operator returns True if there is an exact match, otherwise False will be returned. In contrast, the != operator returns True if there is no match and otherwise returns False. Listing 1 demonstrates this.

In a for loop, a string containing the name of the Swiss city "Lausanne" is compared with an entry from a list of other places, and the comparison result is printed on stdout.

Listing 1:

# define strings
listOfPlaces = ["Berlin", "Paris", "Lausanne"]  
currentCity = "Lausanne"

for place in listOfPlaces:  
    print ("comparing %s with %s: %s" % (place, currentCity, place == currentCity))

Running the Python script from above the output is as follows:

$ python3 comparing-strings.py
comparing Berlin with Lausanne: False  
comparing Paris with Lausanne: False  
comparing Lausanne with Lausanne: True  

The == and is Operators

Python has the two comparison operators == and is. At first sight they seem to be the same, but actually they are not. == compares two variables based on their actual value. In contrast, the is operator compares two variables based on the object id and returns True if the two variables refer to the same object.

The next example demonstrates that for three variables with integer values. The two variables a and b have the same value, and Python refers to the same object in order to minimize memory usage.

>>> a = 1
>>> b = 1
>>> c = 2
>>> a is b
True  
>>> a is c
False  
>>> id(a)
10771520  
>>> id(b)
10771520  

As soon as the value changes Python will reinstantiate the object and assign the variable. In the next code snippet b gets the value of 2, and subsequently b and c refer to the same object.

>>> b = 2
>>> id(b)
10771552  
>>> id(c)
10771552  

A rule of thumb to follow is to use == when comparing immutable types (like ints) and is when comparing objects.

More Comparison Operators

For a comparison regarding a lexicographical order you can use the comparison operators <, >, <=, and >=. The comparison itself is done character by character. The order depends on the order of the characters in the alphabet. This order depends on the character table that is in use on your machine while executing the Python code.

Keep in mind the order is case-sensitive. As an example for the Latin alphabet, "Bus" comes before "bus". Listing 2 shows how these comparison operators work in practice.

Listing 2:

# define the strings
listOfPlaces = ["Berlin", "Paris", "Lausanne"]  
currentCity = "Lausanne"

for place in listOfPlaces:  
    if place < currentCity:
            print ("%s comes before %s" % (place, currentCity))
    elif place > currentCity:
            print ("%s comes after %s" % (place, currentCity))
    else:
            print ("%s is similar to %s" % (place, currentCity))

Running the Python script from above the output is as follows:

$ python3 comparing-strings-order.py
Berlin comes before Lausanne  
Paris comes after Lausanne  
Lausanne is similar to Lausanne  

Case-Insensitive Comparisons

The previous examples focused on exact matches between strings. To allow case-insensitive comparisons Python offers special string methods such as upper() and lower(). Both of them are directly available as methods of the according string object.

upper() converts the entire string into uppercase letters, and lower() into lowercase letters, respectively. Based on Listing 1 the next listing shows how to use the lower() method.

Listing 3:

# using the == operator
listOfPlaces = ["Berlin", "Paris", "Lausanne"]  
currentCity = "lausANne"

for place in listOfPlaces:  
    print ("comparing %s with %s: %s" % (place, currentCity, place.lower() == currentCity.lower()))

The output is as follows:

$ python3 comparing-strings-case-insensitive.py
comparing Berlin with lausANne: False  
comparing Paris with lausANne: False  
comparing Lausanne with lausANne: True  

Using a Regular Expression

A Regular Expression - or "regex" for short - defines a specific pattern of characters. Regarding this topic, Jeffrey Friedl wrote an excellent book titled Mastering Regular Expressions, which I'd highly recommend.

To make use of this mechanism in Python import the re module first and define a specific pattern, next. Again, the following example is based on Listing 1. The search pattern matches "bay", and begins with either a lowercase or an uppercase letter. Precisely, the following Python code finds all the strings in which the search pattern occurs no matter at which position of the string - at the beginning, or in the middle, or at the end.

Listing 4:

# import the additional module
import re

# define list of places
listOfPlaces = ["Bayswater", "Table Bay", "Bejing", "Bombay"]

# define search string
pattern = re.compile("[Bb]ay")

for place in listOfPlaces:  
    if pattern.search(place):
        print ("%s matches the search pattern" % place)

The output is as follows, and matches "Bayswater", "Table Bay", and "Bombay" from the list of places:

$ python3 comparing-strings-re.py
Bayswater matches the search pattern  
Table Bay matches the search pattern  
Bombay matches the search pattern  

Multi-Line and List Comparisons

So far our comparisons have only been on a few words. Using the difflib module Python also offers a way to compare multi-line strings, and entire lists of words. The output can be configured according to various formats of diff tools.

The next example (Listing 5) compares two multi-line strings line by line, and shows deletions as well as additions. After the initialization of the Differ object in line 12 the comparison is made using the compare() method in line 15. The result is printed on stdout (line 18).

Listing 5:

# import the additional module
import difflib

# define original text
# taken from: https://en.wikipedia.org/wiki/Internet_Information_Services
original = ["About the IIS", "", "IIS 8.5 has several improvements related", "to performance in large-scale scenarios, such", "as those used by commercial hosting providers and Microsoft's", "own cloud offerings."]

# define modified text
edited = ["About the IIS", "", "It has several improvements related", "to performance in large-scale scenarios."]

# initiate the Differ object
d = difflib.Differ()

# calculate the difference between the two texts
diff = d.compare(original, edited)

# output the result
print ('\n'.join(diff))  

Running the script creates the output as seen below. Lines with deletions are indicated by - signs whereas lines with additions start with a + sign. Furthermore, lines with changes start with a question mark. Changes are indicated using ^ signs at the according position. Lines without an indicator are still the same.

$ python comparing-strings-difflib.py
  About the IIS

- IIS 8.5 has several improvements related
?  ^^^^^^

+ It has several improvements related
?  ^

- to performance in large-scale scenarios, such
?                                        ^^^^^^

+ to performance in large-scale scenarios.
?                                        ^

- as those used by commercial hosting providers and Microsoft's
- own cloud offerings.

Conclusion

In this article you have learned various ways to compare strings in Python. We hope that this overview helps you effectively programming in your developer's life.

Acknowledgements

The author would like to thank Mandy Neumeyer for her support while preparing the article.

Author image
Berlin -- Genève -- Cape Town Twitter Github
IT developer, trainer, and author. Coauthor of the Debian Package Management Book (http://www.dpmb.org/).