Python “is” versus “==”: Explained using Examples!

In this article let us learn the difference between the often confused “is” and “==” operators and learn when to use which one in our programs!

The first step in the journey towards mastery of any programming language is to learn about the various operators provided by that language and learn how to wield them. Python is no exception to this rule!

Even though the concepts might look simple, our brains are really good at understanding the concepts but not so good at remembering them!

The best trick to make our brains remember stuff is via active learning. By “active learning” I mean “doing”!!

So put on your coding hats, open your laptops and start experimenting and playing with the code shown in the examples as you read them!

The phrase “Practice Makes Perfect” did not survive so many centuries for no reason!

For those of you who came here just to refresh your memories, here is the short version!

Python “is” versus “==”: The Short Answer

What is the difference between the “==” operator and the “is” operator?
The “==” operator is used in verifying that 2 objects have the same value while the “is” operator is used in verifying that 2 references are pointing to the same object.

In other words, the “is” operator is used to verify if 2 objects are one and the same, while the “==” operator only cares about the values contained within a given object.

Let us take a simple example

>>> x = ['a', 'p', 'p', 'l', 'e']
>>> y = ['a', 'p', 'p', 'l', 'e']
>>> x != y
False
>>> x is not y
True

Here

  • the variable “x” and “y” have the same value, but are pointing to 2 different list objects in memory,
  • when invoking the “==” operator we get “True” and
  • when we invoke the “is” operator we get “False” as x is not y, they are 2 different objects(or should I say 2 different apples 😉 )

The main source of confusion is when we play around with these operators in the python interpreter and see something like this

>>> x = "apple"
>>> y = "apple"
>>> x == y
True
>>> x is y
True

What is going on here?

The “==” operator does what we need it to, but what does the “is” operator think it is doing? Shouldn’t it print “False” just like the example above with the lists?

This article is all about answering the above question!

But don’t worry if the above few paragraphs did not make much sense to you, as “the short answer” was focused on people who just wanted to refresh their memories!

This article is specifically crafted keeping beginners in mind, so if you are feeling confused, forget that you ever read the answer above, find a quiet place, focus for the next 10 to 25 minutes, and read the rest of the article. Then come back and read the “short answer” above, I guarantee it will make more sense!

So, let’s begin!

What does “==” operator do?

==” is an operator in Python which is used to compare the equality of 2 objects, be it strings or integers or some special user-defined classes

>>> x = 1
>>> y = 2
>>> x == y
False
>>> y = 1
>>> x == y
True

A Challenge for you!

Before reading the next paragraph I want you to look at the code above and first come up with your own explanation on why the code does what it does. The practice of “Reading code with intent” will get you from being a “noob” to an “expert” in no time!

Are you ready? Okay, time for the explanation!

In this simple session at the Python interpreter,

  • object x is assigned a value of 1 and
  • object y is assigned a value of 2. Then
  • when we compare for equality in line-3 using the “x == y“, the Python interpreter returns False. Then
  • y is reassigned to 1, and the equality between x and y is checked again, and this time we get True just as we expected.

Side Note

If you are not clear on the “==” operator, I suggest you read my other article mentioned below first and then come back here!

Python’s “==” Explained Using 12 Examples

There I have explained

  • How to use the “==” operator in the interpreter and in programs
  • How is the “==” operator implemented inside Python
  • How to redefine the behavior of the “==” operator for the classes that we define.

So go ahead and read that article (at least till LEVEL#2) and then come back here!

What does the “is” Operator do?

The “is” operator is used to verify if 2 references are pointing to the same object.

As you can see there are 3 men in the picture, and each one has a name.

Now consider the “Mathew”, he can be also called with the name “Matt”. So no matter if you use the name “Mathew” or “Matt” they both refer to the same guy in the brown suit!

The same goes with “Thomas” a.k.a “Tom” and James a.k.a Jim.

Let us write a simple program to see what I mean

Mathew = "the guy in the Brown Suit"
Matt = Mathew

Thomas = "the guy in the Blue Suit"
Tom = Thomas

print("Mathew is ", Matt)
print("Tom is ", Thomas)

Another Code Reading Challenge!

Okay, now that you have read the code, time for a challenge!

Before reading on, try to answer this question!

What output do you think this code will print?

Alright, now let us see if you got the answer correct!

This will give an output like this

Mathew is the guy in the Brown Suit
Tom is the guy in the Blue Suit

As you can see, it doesn’t matter whether you use the name “Mathew” or “Matt”, they both refer to “the guy in the Brown Suit”!

Hence we can say that

Mathew and Matt are references to the guy in the Brown suit

Whenever you create an object in Python, the object gets an “ID”, something like our social security number if you are in the USA or the personal ID code if you are in Europe.

If we want, we can also have a look at this “ID” using the id() function as shown below

>>> id(Mathew)
139633218611568
>>> id(Matt)
139633218611568

As you can see they both have the same “ID” number!

This is what we want as they are both referring to the same person!

I leave it up to you to verify if the ID for (Tom, Thomas) and (Jim, James) are the same!

We refer to “Mathew” as the formal name and “Matt” as the nickname.

In the computer programming world, the names which are referring to an object with a given ID are called “References”!

Side Note

If you are still not clear about the “is” operator, I suggest reading my other article on the “is” and “is not” operators.

Python “is” and “is not”: Explained Using 14 Examples!

There I have explained

  • what are “is” and “is not” operators
  • when and where to use the “is” and “is not” operators
  • how these operators are implemented under the hood, etc,.

So go ahead and read that article and then come back here!

Reason the “is” Operator behaves differently with Strings and Lists

Now that we have understood the meaning of “is” and “==” operators, let us get back to the main question this article is trying to answer, the behavior that confuses a lot of people,

Why does the “is” operator behave differently with strings and lists?

Have a look at the following 2 interpreter sessions.

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> x == y
True
>>> x is y
False
>>> a = "apple"
>>> b = "apple"
>>> a == b
True
>>> a is b
True

Beginners often get confused when they see something like this, which is completely normal, even I was bewildered when I saw this for the first time around!

In this first example,

  • we have 2 list objects, each with the same contents “[1, 2, 3]“.
  • When we compare them using the “==” operator we get “True“, but
  • when we compare them with the “is” operator we get “False

In the second example, we basically do the same, but this time the variables “a” and “b” are storing the string “apple” instead, but both the “is” and the “==” operator returns True.

This can be explained using the built-in “id()” function as before, if you check the ids of x, y, a, and b.

>>> id(a)
139704859524208
>>> id(b)
139704859524208
>>> id(x)
139704858154368
>>> id(y)
139704858155200

As you can see, the id’s of “a” and “b” are the same, while the id’s of “x” and “y” are different.

Problem-Solved right?

Ya, I don’t think so too!

How come lists have different IDs, while strings have the same IDs?

This is because of a concept called “mutability” in Python.

Mutability

Time for another Challenge!

Before reading this section, I want you to google the words “mutability” and “mutable” to understand their meanings in plain English, that will give you a better perspective on what follows!

In Python, strings are immutable objects, which means once they are created their values cannot be changed.

>>> a = "Hello"
>>> id(a)
139704858663216
>>> a = "Hi"
>>> id(a)
139704858512432

As you can see in the example, in line-1 we have assigned the string “Hello” to variable “a”. After this line is executed, Python will create the string object “Hello” in memory and the variable “a” will refer to this memory location as shown below

Then after executing line-4 in the example above, the working memory of Python will look like this instead

As you can see a brand new string object with the value “Hi” and ID 139704858512432 is created in the memory and the variable “a” is now pointing to this new object.

Even if you do something simple like shown below, the ID will change

>>> a = "Hello"
>>> id(a)
139704859813296
>>> a = a + " World!"
>>> a
'Hello World!'
>>> id(a)
139704858512432

So the point to remember here is

Python does not edit the strings in place and even editing a single letter in a string will result in a brand new string and a change of ID

Now let us look at lists

>>> list1 = [1, 2, 3]
>>> id(list1 )
139704858268800
>>> list1 .append(4)
>>> list1 
[1, 2, 3, 4]
>>> id(list1 )
139704858268800

As you can see, the ID of the list “list1” did not change before and after appending the number 4 to its end. This is because, unlike strings, Lists are mutable objects, which means lists can be edited in place.

But then the next question that will come to your mind is

Why are some types mutable while others are immutable?

This is because “mutability” and “hashability” are directly related to one another as the hash of an object is usually derived from the object’s ID.

Side Note: What are Hashes?

So what is this “hash” then?

Hash is nothing but a number that an algorithm spits out taking some digital data as input.

What is special about the output number, a.k.a “the hash” is that no matter what the length of the input is, the output is always of fixed length, and the same input always gives out the same output.

Hashes are used everywhere. A good example is sometimes when we download something off the internet, we will get a short text file along with it, containing a hash named SHA or MD5 (SHA and MD5 are nothing but hashing algorithms) which can be used to verify if the file we downloaded is indeed perfect!

They are also used in our filesystems to check the integrity of our files before opening them.

How is hash calculated in python? The ID of a given object is given as input to the hash function to get the hash as shown below.

>>> x = "apple"
>>> hash(x)
-4546430606256924472

Where is “hash” used for in python?
Hash decided the “uniqueness” of an object, which is important in many scenarios while coding in python.

One example that comes straight to mind is “set”.

By definition, A set is a collection of unique objects, so we need a way to know if a given element is already in the set or not.

So for example

>>> set1 = {'1', '2', '3'}
>>> set1.add('4')
>>> set1
{'1', '2', '3', '4'}
>>> set1.add('3')
>>> set1
{'1', '2', '3', '4'}

How does python know not to add 3 again to the set?

Python maintains a table of hashes and it first checks if a given ID is already present in the hash table or not and only adds elements that are not present in the list.

This hash table entry is only added at the moment the element is added to the set, hence we need to make sure that the element cannot be changed once it is created!

For this reason, Python only allows immutable object types to be added to lists!

Let us see what happens if we try to add a List as a set element!

>>> set1.add([1,2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

As you can see we get a TypeError saying list is an “unhashable type” and hence cannot be added to the set!

If you ever need to have a list of items as a set element, Python provides us with the “tuple” datatype to represent immutable lists!

>>> set1.add((1,2))
>>> set1
{1, 2, (1, 2), 3, 4}

As you can see, now the tuple (1,2) is added to the set without any errors as tuples are immutable!

When to use “==” and when to use “is”

Now that we have learned how these 2 operators work, the time has come to see how these tools can be put to good use in our programs!

Time for another Challenge!

We already have all the clues needed to answer the question

When to use “==” and when to use “is” in our programs?

So go ahead and spend a couple of minutes to come up with your own theory before reading on!

A good time to use the “==” operator

Anytime the value of 2 objects needs to be compared for equality, we should use the “==” operator.

Take a look at the following Python program

ans1 = input("What kind of chocolate you like? press 1 for dark and 2 for white: ")
if ans1 == "1":
  print("More the cocoa, better the chocolate!")
elif ans1 == "2":
  print("Whiter the chocolate the yummier it tastes!")
else:
  print("Invalid input!")

ans2 = input("What is you phone's theme mode? press 1 for dark-mode and 2 for light-mode: ")
if ans2 == "1":
  print("Dark mode looks the coolest!")
elif ans2 == "2":
  print("Light mode is simply classic!")
else:
  print("Invalid input!")

I have written an entire article dedicated to the “==” operator as shown in the link below.

Python’s ‘==’ Operator: Meaning and Usage Explained with Examples

There you can find many more use-cases, examples, and in-depth information on how to use the “==” operator!

A good time to use the “is” operator

Type checking is not done by default in Python functions, the is operator is very useful in such scenarios to make sure that the arguments received are valid.

#Example 1

x = [1, 2, 3]
y = (1, 2, 3)

if type(x) is list:
  print("x is mutable, lists are flexible, lists are the best!")

if type(y) is tuple:
  print("y is immutable, nobody can mess with tuples, tuples are awesome!")

This gives an output like this

x is mutable, lists are flexible, lists are the best!
y is immutable, nobody can mess with tuples, tuples are awesome!

As you can see both the print statements got executed, which means both the conditions in the if statement got evaluated to be True

Unlike the other examples, instead of comparing the ID of 2 objects, we are comparing the ID of 2 types this time!

>>> id(type(x))
9461280
>>> id(list)
9461280
>>>

As you can see even the object types have IDs and they match!

Assume we have a function that calculates the area of a square as shown below.

def calculateAreaOfSquare(side):
  if (type(side) is int) or (type(side) is float):
    print("Area = ", side*side)
  else:
    print("Invalid Input to the function")
>>> calculateAreaOfSquare(4)
Area =  16
>>> calculateAreaOfSquare(5.5)
Area =  30.25
>>> calculateAreaOfSquare("five")
Invalid Input to the function

we expect the user of this function to provide either an integer or a float as input. To make sure that the input is valid we are using the built-in type() function along with the “is” operator as shown above.

There are 2 other special use-cases of the “is” operator

  • usage with “None”
  • usage with “NotImplemented

Both these use-cases have been explained in great detail in my other article in the link below.

Python “is” and “is not”: Explained Using 14 Examples!

The main thing to keep in mind is that always go with the “is” operator instead of using the “==” operator when doing comparisons with “None” and “NotImplemented”

The reason the is operator works is due to the fact

None” and “NotImplemented” objects are singletons in Python, meaning only one of these objects will be present in the memory!

Hence, because of the facts

  • the equality operators can always be customized to give out anything we want it to, and
  • there is only one “None” object in the memory, we should always use the “is” operator with None and NotImplemented.

use “is” with “None” and “NotImplemented” and not “==”

Where To Go From Here?

Bravo again! I admire your hunger for learning, and your spirit to go over obstacles to achieve mastery in your craft!

At this point, I suggest you play around with these operators till they become second nature.

Once you feel you have mastered these operators, go ahead and choose your next read from the “Related Articles” section below!

I hope you found this article useful.

Feel free to share this article with your friends and colleagues!

Related articles

Python: “is not” vs “!=” Similarities and Differences

Python “in” and “not in”: Explained Using 8 Examples!

Python’s ‘==’ Operator: Meaning and Usage Explained with Examples

Python’s ‘!=’ Operator: Meaning and Usage Explained with Examples

References

  1. Expressions
  2. PEP8

Photo of author
Editor
Balaji Gunasekaran
Balaji Gunasekaran is a Senior Software Engineer with a Master of Science degree in Mechatronics and a bachelor’s degree in Electrical and Electronics Engineering. He loves to write about tech and has written more than 300 articles. He has also published the book “Cracking the Embedded Software Engineering Interview”. You can follow him on LinkedIn