In this article let us learn how to implement the “if not” logic in our Python programs with the help of some examples!
If you are in a hurry, here is the short version of the answer!
The Short Version of the Answer
In Python, depending on what we are trying to do, we can implement “if not” logic in the following 2 ways
Situation#1: Checking if a condition has failed
If you are in a situation where you wish to proceed when a condition has failed, then you can implement the “if not” logic using the syntax below.
if <condition> == False:
// do your cool stuff here
Remember the fact that all conditions will evaluate to the Boolean values of either True or False. We just used the same in the syntax above to verify if our condition has evaluated to False to make sure that the condition has indeed failed.
Let us see an example usage of the syntax above
is_iron_man_in_justice_league = False
if is_iron_man_in_justice_league == False:
print('Iron man is not part of the justice league of america')
This is just a simple example, but you get the idea!
Situation#1: Checking if 2 objects are not equal
If your situation requires you to compare 2 objects and make sure they are not equal before proceeding, then you can implement the “if not” logic with the help of != operator (stands for “not equal to”)
The syntax below shows the usage of != operator
if obj1 != obj2:
// do your cool stuff here
Let us see the usage using an example!
x = 5
y = 10
if x != y:
print('x is not equal to y')
else:
print('x is equal to y')
The output of the above code obviously will be
x is not equal to y
Let us see take another example to have a look at things from a slightly different perspective.
list1 = [1, 2, 3, 4, 5]
list2 = ['apple','mango','orange','pineapple','kiwi']
if list1 != list2:
print('list1 is not equal to list2')
else:
print('Both lists are equal')
The output will now look like the following
list1 is not equal to list2
As you can see, the output is just as expected!
As you can see, the same ‘!= operator‘ is used for comparing 2 integers and for comparing 2 lists!
In fact, all built-in python objects will support comparisons using the ‘!= operator‘ and even most of the external libraries (if properly built) will do the same!
It sure does make the lives of us the programmers easy! But the curious ones among you will have the following questions popping up in your minds.
- How does python makes sure that all in-built objects obey the “!= operator” as we intuitively expect them to?
- How do we make sure that the classes we define ourselves obey the “!= operator“?
The rest of this article is all about answering these 2 questions!
“if not” in Python: The More Informative Version of the Answer
If you prefer videos to articles, here is a short video I have made for you on this topic!
(I am a newbie YouTuber so go easy on me if the quality is not matching your expectations!)
Okay, let us get back to the article!
Expressions and Operators: Some Background Info
First let us get back to the basics, and have a look at how “if” statements work in Python.
The general syntax of if statements is shown below
if <expression is True>:
# Execute code here
else:
# Execute code here
The part to note here is “expression is True”.
An expression is a condition that will evaluate to either True or False
Let us see a few examples of such “expressions“
x = 5
if x > 6:
print ('x is greater than 6')
else:
print ('x is not greater than 6')
Here the expression: x > 6 will evaluate to False and the line x is not greater than 6 will get printed on our screens.
The following table shows the 6 comparison operators supported with integer objects.
Operator | Meaning | Usage |
== | integer1 is equal to integer2 (since = is already reserved for assignment operations, we use the “==” operator to check for equality) | x == y |
!= | integer1 is not equal to integer2 | x != y |
> | integer1 is greater than integer2 | x > y |
< | integer1 is less than integer2 | x < y |
>= | integer1 is greater than or equal to integer2 | x >= y |
<= | integer1 is less than or equal to integer2 | x <= y |
In Python, the engineers who built the language, have tried to extend the behavior of these comparison operators to apply to all of the in-built datatypes such as strings, lists, sets, dictionaries, etc.
Each of these datatypes will support a subset of these 6 comparison operators.
For example, in string datatype variables, all 6 characters are supported as shown in the code example below
>>> a = 'apple'
>>> b = 'mango'
>>> a == b
False
>>> a != b
True
>>> a < b
True
>>> a > b
False
>>> a <= b
True
>>> a >= b
False
Greater than and less than in strings use the alphabetical order to determine which one is greater. In this example, apple comes before mango in the dictionary, hence if the whole dictionary is thought of as a list of words, then the index of apple will be smaller than the index of mango and hence we got the above output.
Hence we get the answer for
is apple less than mango? to be True
But in lists, not all 6 operators are implemented as shown in the code below.
>>> list1 = [1, 2, 3, 4, 5]
>>> list2 = ['a', 'b', 'c']
>>> list1 == list2
False
>>> list1 != list2
True
As you can see, the equality checks works fine, now let us see if greater than and less than works
>>> list1 < list2
TypeError: '<' not supported between instances of 'int' and 'str'
As you can see, python throws an error here.
This is because, it intuitively makes sense to check if 2 lists are equal or not, but it does not make sense to check which one is greater than the other!
Hence the engineers who designed python did not implement code that will do > or < comparison for us when it comes to lists.
Okay now that we have covered the background stuff, let us get back to the main topic which is to understand how exactly these operators are implemented behind the curtains!
Python’s implementation of “if not” using “!= operator“
In Python, the != operator is implemented with the help of __ne__() method. Here “ne” stands for “not equal“. Almost all classes in Python will come in-built with this method.
Whenever we use the ‘!=’ operator, the python interpreter calls this __ne__() function to do the comparison.
So when we write
object1 != object2
Python will interpret and transform the code into
object1.__ne__(object2)
Python will then run the __ne__() method, and returns us either True or False.
The actual logic for comparison of the 2 objects is implemented inside the __ne__() method of a given class. This implementation will vary depending on the datatype we are dealing with. As we saw in the previous section, the implementation of __ne__() for integers will not be the same as the implementation of __ne__() for strings!
Let us see a simple example of how we can directly call the __ne__() function instead of using the != operator and get the same result!
x = 'a'
if x.__ne__('b'):
print ('x is not equal to b')
If you run the code above, you will get the following as result
x is not equal to b
As you might have guessed, other operators like “>”, “<“, “==”, “<=” and “>=” are also implemented as methods as shown in the table below.
Operator | Meaning | Method |
== | is equal to | __eq__() |
!= | is not equal to | __ne__() |
> | is greater than | __gt__() |
< | is less than | __lt__() |
>= | s greater than or equal to | __ge__() |
<= | s less than or equal to | __le__() |
As a side note, whenever you see methods with 2 underscores (pronounced in the python community as ‘dunder’) in any python code, you can infer that these are methods designed to do what we would want a particular operator to intuitively do, like __ne__() for != and __eq__() for ==.
The below code example shows the usage of these methods.
>>> x = 5
>>> y = 10
>>> x.__gt__(y)
False
>>> x.__lt__(y)
True
>>> x.__le__(y)
True
>>> x.__ge__(y)
False
>>> x.__eq__(y)
False
Whenever you are using some classes from 3rd party libraries and your code doesn’t work right, it is recommended that you use this method to debug and verify that __ne__() and __eq__() methods are implemented correctly in those classes!
If you declare your own classes, it is recommended that you implement some of these methods (which you think are appropriate to your classs) so that users of your classes would have the ability to do comparison operations using operators. In the next section, let us see how to do this!
Implementation of __ne__() methods in our own classes
To refresh your memory, classes are just a way to store related data and functions together.
The code below shows the implementation of __ne__() method in a custom class defined by us.
class Avenger():
def __init__(self, name):
self.name = name
def __ne__(self, obj):
print("reached __ne__()");
if self.name != obj.name:
return True
else:
return False
avenger1 = Avenger('Thor')
avenger2 = Avenger('Hulk')
if avenger1 != avenger2:
print('These 2 avengers are not equal!')
Here the Avenger class has only one class variable: name and the __ne__() method simply compares if the names are equal or not.
Running this code gives the following output.
reached __ne__()
These 2 avengers are not equal!
Note the 1st line above “reached __ne__()” which is also the 1st line inside the __ne__() method (line-6).
See how the python interpreter took the “!=” operator and made the connection to our __ne__() method, just like we wanted it to!
Behind the curtains, the interpreter took the following steps to make the connection from “!=” to __ne__()
- avenger1 != avenger2 => avenger1.__ne__(avenger2)
- avenger1.__ne__(avenger2) => __ne__(avenger1, avenger2)
- __ne__() returned False as the names were not equal.
Following a similar logic, we can also implement other methods such as __eq__(), __gt__(), __lt__(), etc.
And with that, I will conclude this article.
I hope you enjoyed reading the article as much as I enjoyed writing it!
Feel free to share this article with your friends and colleagues!
References
Python.org: Datamodel
Python.org: Expressions
Stack Overflow Question