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
!=. 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.
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.
# 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
Python has the two comparison operators
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
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
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
>=. 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.
# 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
The previous examples focused on exact matches between strings. To allow case-insensitive comparisons Python offers special string methods such as
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
# 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.
# 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).
# 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.
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.
The author would like to thank Mandy Neumeyer for her support while preparing the article.