2.3. OOP Comparison

  • = assignment

  • == checks for object equality

  • is checks for object identity

In Python, identity and value comparison are two different ways of comparing objects. Identity comparison (is operator) checks whether two objects are the same object in memory, i.e. whether they have the same memory address. Value comparison (== operator) checks whether two objects have the same value, i.e. whether they are equal according to their values.

Here's an example to illustrate the difference between identity and value comparison:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]

Identity comparison:

>>> a is b
False

Value comparison:

>>> a == b
True

In this example, a and b are two different objects in memory, even though they have the same value. The identity comparison using the is operator returns False, because a and b are not the same object in memory. The value comparison using the == operator returns True, because a and b have the same value.

It's important to note that identity comparison (is operator) is more strict than value comparison (== operator). If two objects are identical, they are also equal in value. However, two objects that are equal in value are not necessarily identical. In general, it's more common to use value comparison (== operator) when comparing objects in Python, unless you specifically need to check whether two objects are the same object in memory.

2.3.1. Performance

  • Date: 2024-08-06

  • Python: 3.12.4

  • IPython: 8.26.0

  • System: macOS 14.5

  • Computer: MacBook M3 Max

  • CPU: 16 cores (12 performance and 4 efficiency) / 3nm

  • RAM: 128 GB RAM LPDDR5

Bool:

>>> x = True
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... x == True
12.1 ns ± 2.83 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... x is True
9.83 ns ± 2.85 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)

None:

>>> x = None
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... x == None
11.1 ns ± 6.27 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... x is None
9.54 ns ± 2.28 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)>>>

Type checking of builtin objects:

>>> x = 1
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... type(x) == int
18.7 ns ± 3.18 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... type(x) is int
8.87 ns ± 7.36 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)

Type checking of custom objects:

>>> class User:
...     pass
>>>
>>> x = User()
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... type(x) == User
19.9 ns ± 3.22 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 1000  
... type(x) is User
13.8 ns ± 2.56 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)