In this article let us learn the difference between the often confused “is not” 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 of the answer!
Python “is not” versus “!=”: The Short Answer
What is the difference between the “!=” operator and the “is not” operator?
The “!=” operator is used to verify that 2 objects have the different values while the “is not” operator is used to verify that 2 references are pointing to 2 different objects.
In other words, the “is not” operator is used to verify if 2 references are not pointing to the same object, while the “!=” operator only cares about the values contained within a given object.
Let us take a look at 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 variables “x” and “y” 2 different lists initialized with [‘a’, ‘p’, ‘p’, ‘l’, ‘e’] ,
- when invoking the “!=” operator we get “False” as the values are the same
- when we invoke the “is not” operator we get “True” as x is not y, as they are 2 different list objects living in different places in memory (or should I just 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
False
>>> x is not y
False
What is going on here?
The “!=” operator does what we need it to, but what does the “is not” operator think its doing? Shouldn’t it print “True” 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 the “!=” operator do?
‘!=’ is an operator in Python which is used to verify the non-equality of the value of 2 objects, be it strings or integers or some special user defined classes
>>> x = 1
>>> y = 2
>>> x != y
True
>>> y = 1
>>> x != y
False
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.
- when we compare for non-equality in line-3 using the x != y, the Python interpreter returns True
- then y is reassigned to 1, and the non-equality between x and y is checked again, and this time we get False 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 ‘!=’ Operator: Meaning and Usage Explained with 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 not” operator do?
The “is not” operator is used to verify that the 2 given references are not 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
>>> Matt is not Mathew
False
>>> Thomas is not Tom
False
>>> Matt is not Tom
True
Another Code Reading Challenge!
Again, try to read the code and come up with an explanation by yourself before looking at the explanation!
As you might have guessed, it doesn’t matter whether you use the name “Mathew” or “Matt“, they both refer to “the guy in the Brown Suit“
Hence we get “False” when we do the comparison between Matt and Mathew. The same goes for Tom and Thomas!
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 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 and Thomas 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: How ID numbers are always unique?
These ID numbers are basically addresses in the memory in which an object is stored. You can think of “Memory location” as a book slot number in a library, only one book can occupy a given book slot, similarly, only one object can occupy a memory slot, and that is how Python ensures that a given “id()” is always unique!
Let us take our same “Matt” and “Mathew” example. Say I ask you a True or False question
is Matt not the same person as Mathew?
You would say “False”. Python does the exact same this using the “is not” operator!
>>> Matt is not Mathew
False
Now if I ask “is Tom and Mathew the same person?” you would say “True”.
>>> Tom is not Mathew
True
Simple as that!
Side Note
If you are still not clear about the “is not” 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 not” Operator behaves differently with Strings and Lists
Now that we have understood the meaning of “is not” 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 not” operator behaves differently with strings and lists?
Have another look at the following 2 interpreter sessions.
>>> x = ['a', 'p', 'p', 'l', 'e']
>>> y = ['a', 'p', 'p', 'l', 'e']
>>> x != y
False
>>> x is not y
True
>>> a = "apple"
>>> b = "apple"
>>> a != b
False
>>> a is not b
False
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 “[‘a’, ‘p’, ‘p’, ‘l’, ‘e’]”.
- when we compare them using the “!=” operator we get “False“, but
- when we compare them with the “is not” operator we get “True“
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 not” and the “!=” operator returns False.
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 not”
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 not” 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 non-equality, we should use the “!=” operator. Here are some simple examples
Take a look at the following Python program
yourCar = input("Please enter the name of your car's manufacturer: ")
yourFavCar = input("Please enter the name of your favorite car manufacturer: ")
if yourCar != yourFavCar:
print("It is time to get a " + yourFavCar + "!!")
else:
print("You have a great car!")
The example above is pretty self-explanatory.
- We are getting 2 inputs from the user,
- the first one asks the user’s present car manufacturer’s name and then
- second one asks the user’s favorite car manufacturer’s name.
- These 2 objects are then compared for inequality and based on the the result we give some suggestions to the user.
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 not” operator
You should consider using the “is not” operator is whenever you are comparing an object to “None” or “NotImplemented“
“None” is a keyword in Python, similar to “NULL” in other languages, used to denote the absence of a value.
Let us have a look at a simple example.
def divide(x,y):
if y != 0:
return x/y
else:
return None
The above function is a very simple function, which takes in 2 numbers, divides the 1st number by the 2nd, and returns the result.
We know that in math, dividing by zero is illegal, and hence we return None if the 2nd number is 0.
Now we can make use of the function as shown below
# Get 2 numbers as input from the user
x = float(input("please enter the 1st number: "))
y = float(input("please enter the 2nd number: "))
quotient = divide(x,y)
if quotient is not None:
print ("x/y = ", quotient)
else:
print ("Divide by Zero is not allowed")
Running this code will give some output like this
please enter the 1st number: 2.5
please enter the 2nd number: 5
x/y = 0.5
please enter the 1st number: 5
please enter the 2nd number: 0
Divide by Zero is not allowed
But why can’t we just use the equality operators like “==” and “!=” instead?
We will get to that question right after our next example of using the “is not” operator with NotImplemented!
“NotImplemented” is a keyword in Python, used to denote that some expected functionality is not implemented in the code.
Consider the function below
def square_root(x):
if x >= 0:
return x**0.5
else:
return NotImplemented
I assume you know that the square root of a negative number is a complex number, if you didn’t you do now!
Our programmer is a little lazy, so he programmed the square_root() function to only calculate roots of positive numbers.
You can use the function in your code like this.
print("This program will calculate the square root of any given number!")
x = float(input("please enter a number: "))
y = square_root(x)
if y is not NotImplemented:
print(f"Square root of {x} is {y}")
else:
print("Our programmer is lazy, please use only positive numbers")
Running the code above will give an output like this!
please enter a number: 25
Square root of 25.0 is 5.0
please enter a number: -50
Our programmer is lazy, please use only positive numbers
Coming back to the question:
Why can’t we just use the equality operators like “==” and “!=” instead?
We could have used the “!=” operator with both None and NotImplemented and have gotten the exact same result, but there are 2 reasons for not doing so
Reason#1: Readability
Using the “is not” operator makes the code more readable hence whenever you come across a situation where you might need to use None or NotImplemented, the official Python documentation PEP8 recommends we use the “is not” operator!
Reason#2: Flexibility of the equality operators can end up working against us!
But why Python specifically recommends this?
This recommendation is because of the fact that the non-equality operators can always be customized to give out anything we want it to, but there is only one “None” object in the memory!
Consider the code below.
>>> obj1 = None
>>> obj1 != None
False
>>> obj1 is not None
False
Everything works fine, no issues whatsoever here! We are using the built-in non-equality operator here so we did not face any issues.
Now consider a class like below with the stupidest-ever equality function!
# A bad class that always return true no matter what!
class BadAtEquality():
def __ne__(self, object):
return False
This class overrides the “!=” operator with a stupid function, which always returns true no matter what the object is compared with!
If we use this function in code we get something like this
>>> obj1 = BadAtEquality()
>>> obj1 != "apple"
False
>>> obj1 != [1, 2, 3]
False
>>> obj1 != None
False
>>> obj1 is not None
True
The situation in Lines 2 to 7 in the session above is what we are trying to avoid!
If we wanted to compare an object with None, we better go with the “is not” operator instead of using the “!=” operator to avoid unnecessary surprises!
Shout out to Alok Singhal at stackoverflow.com for this nice example!
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!