Table of Content
- What is the Equality (==) Operator?
- What is the “is” Keyword Operator?
- What's the difference between the equality (==) operator and “is” in Python?
- When Should is Keyword Operator be used?
- When Should == Operator be Used?
- Issues with using 'is' to check for Equality
- Inferring equality from identity
- Extra point to keep in mind
- Conclusion
The equality operator ==
and is
keyword are two features in Python that are used to compare values.
The equality operator ==
compares the values and is
operator compares the references.
In this post, you will learn about the equality operator ==
and the is
keyword, the difference between both, and when to use them.
What is the Equality (==) Operator?
The equality operator is used to compare two values of the objects/variables.
It returns True
if both the values are equal and False
if they are not equal.
This is useful when you want to check if two objects contain the same content or not.
Example of how to use the Equality (==) Operator
Output
The equality check returns True as both the values are equal.
What is the “is
” Keyword Operator?
The “is” keyword operator is used to check if two variables are pointing to the same object in memory.
This is useful when you want to check if the object is a singleton (objects with one reference in memory) like None
, True
, False
, etc. as they check for identity.
It also checks if the object is of a particular type or not.
Example of how to use the “is
” Keyword Operator
Output
In the above example, the result of the identity operator is True as both the values have the same location in the memory.
id()
is the Python built-in function that returns the memory location of an object.
Let's see another example:
Output
In the above example, the result of the identity operator is False, as both the values have different locations in the memory.
What's the difference between the equality (==) operator and “is” in Python?
The equality operator ==
is used for value equality to know if two objects have the same value while the is
keyword is for reference equality to know if two variables point to the same object in memory.
==
: check for equality - the semantics are that equivalent objects (that aren't necessarily the same object) will test as equal.
According to the documentation:
The operators <, >, ==, >=, <=, and != compare the values of two objects.
is
: check for identity - the semantics are that the object (as held in memory) is the object.
According to the documentation:
*The operators is
and is not
test for object identity: x is y
is true if and only if x
and y
are the same objects.
Object identity is determined using the id()
function. x is not y
yields the inverse truth value.*
Thus, the check for identity is the same as checking for the equality of the IDs of the objects. That is,
a is b
is the same as:
id(a) == id(b)
Where id
is the built-in function that returns an integer that “is guaranteed to be unique among simultaneously existing objects” (see help(id)
) and where a
and b
are any arbitrary objects.
When Should is
Keyword Operator be used?
The is
Keyword Operator should be used when:
-
you want to compare a value to a Python constant. The constants in Python are:
None
True
1False
1NotImplemented
Ellipsis
__debug__
- classes (for example
int is int
orint is float
) - there could be additional constants in built-in modules or 3rd party modules. For example
np.ma.masked
from the NumPy module.
Other situations where is
keyword operator can be used include:
None
- enum values (when using Enums from the enum module)
- modules
- class objects resulting from class definitions
- function objects resulting from function definitions
- Anything else that should only exist once in memory (all singletons, generally)
- A specific object that you want by identity
When Should ==
Operator be Used?
Here are situations where ==
operator can be used:
- numbers, including integers
- strings
- lists
- sets
- dictionaries
- custom mutable objects
- other built-in immutable objects, in most cases
The PEP 8, the official Python style guide for the standard library also mentions two use-cases for is
:
-
Comparisons to singletons like
None
should always be done withis
oris not
, never the equality operators. -
Also, beware of writing
if x
when you really meanif x is not None
– e.g. when testing whether a variable or argument that defaults toNone
was set to some other value.
The other value might have a type (such as a container) that could be false in a boolean context!
Issues with using 'is
' to check for Equality
There are some inconsistent behaviors in Python when you use 'is' to check for Equality.
Let's run this small example.
Output
The behavior is expected, just like what we saw in the previous example.
Let's now replace 1000 with 100.
Output
What happened here? This is inconsistent with the previous result.
It turns out, the reference implementation of Python caches integer objects in the range -5…256 as singleton instances for performance reasons.
You can see that when we have small numbers like 50 in the first example, they have same the memory locations. But when we have large numbers like 500 in the second example, they have different memory locations. Why?
This is because interpreters in CPython interns smaller numbers to a fixed memory location to save memory as they are frequently used.
Generally, the range of numbers is -5 to +256, but it can vary according to your interpreter.
Any number outside this range is interned to a different memory location. That's why a large number like 500 returns False.
The same thing happens for strings as well.
Let's see the example below:
>>> s = b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)
Now everything seems fine.
>>> s = 'somestr'
>>> b = 'somestr'
>>> s == b, s is b, id(s), id(b)
(True, True, 4555519392, 4555519392)
That's expected too.
>>> s1 = b1 = 'somestrdaasd ad ad asd as dasddsg,dlfg ,;dflg, dfg a'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, True, 4555308080, 4555308080)
>>> s1 = 'A quick brown fox jumps over the lazy dog'
>>> b1 = 'A quick brown fox jumps over the lazy dog'
>>> s1 == b1, s1 is b1, id(s1), id(b1)
(True, False, 4555308176, 4555308272)
Now that's unexpected.
Inferring equality from identity
If is
is true, equality can usually be inferred - logically, if an object is itself, then it should test as equivalent to itself.
In most cases, this logic is true, but it relies on the implementation of the __eq__
special method. As the docs say,
The default behavior for equality comparison (
==
and!=
) is based on the identity of the objects. Hence, equality comparison of instances with the same identity results in equality, and equality comparison of instances with different identities results in inequality. A motivation for this default behavior is the desire that all objects should be reflexive (i.e. x is y implies x == y).
and in the interests of consistency, recommends:
Equality comparison should be reflexive. In other words, identical objects should compare equal:
x is y
impliesx == y
We can see that this is the default behavior for custom objects:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
The contrapositive is also usually true - if something tests as not equal, you can usually infer that they are not the same object.
Since tests for equality can be customized, this inference does not always hold true for all types.
Extra point to keep in mind
A notable exception is nan
- it always tests as not equal to itself:
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
Checking for identity can be a much quicker check than checking for equality (which might require recursively checking members).
But it cannot be substituted for equality where you may find more than one object as equivalent.
Note that comparing the equality of lists and tuples will assume that identity of objects are equal (because this is a fast check).
This can create contradictions if the logic is inconsistent - as it is for nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
Conclusion
In this tutorial, you have learned the difference between the equality
operator and the is
keyword and how to use them.
The difference between the equality
operator and is
operator is that is
operator checks the identity of the objects and the equality
operator checks the equality of the objects.
Do not use is
to compare integers and strings.
If you learned from this tutorial, or it helped you in any way, please consider sharing and subscribing to our newsletter.
Please share this post and for more insightful posts on business, technology, engineering, history, and marketing, subscribe to our newsletter.