The Built-In id() Function

by Christoph Schiessl on Python

In addition to equality, you can also compare objects in Python based on their identity. Object identities are represented by simple int values that you can retrieve using the built-in id(object) function. All Python objects, without exception, have a unique identity. The official documentation explains the id() function as follows:

Return the "identity" of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

So, all objects in existence at any given time have unique identities.

Python 3.12.2 (main, Feb 17 2024, 22:03:42) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> x, y = object(), object()
>>> id(x), id(y) # Two distinct objects have distinct identities.
(131886824916736, 131886824916784)
>>> id(x), id(y) # Identities never change => they are constant.
(131886824916736, 131886824916784)

So far, so good. The documentation explicitly said that the uniqueness of identities does not hold for objects whose lifetimes do not overlap, and this behavior is testable. Observe:

Python 3.12.2 (main, Feb 17 2024, 22:03:42) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> prev_ids: set[int] = set()
>>> while True:
...     current_id: int = id(object())
...     if current_id in prev_ids:
...         print(f"Identity of the {len(prev_ids) + 1}th object was seen before!")
...         break
...     prev_ids.add(current_id)
...
Identity of the 2th object was seen before!

On my machine, the second object created had the same identity as the first one, which is no longer accessible (no references to it are in scope). This is implementation-specific, but if you use CPython, as I am, the first object has been garbage-collected. I can be sure of that because CPython object identities are nothing more than memory addresses. So, if the same memory address appears again for a different object, this must mean that the garbage collector has freed the object that previously occupied this memory address.

When I wrote this program, I didn't expect to get a repeated memory address for the second object, but it doesn't matter. The lifetime of the first object has ended, and therefore, the memory address it used to occupy is available for other objects. Second or not, the id() uniqueness, as required by the specification, has not been violated!

is and is not Operators

Object identities come into play when using the is operator. For instance, if you imagine two references, a and b, you can compare the identities of the objects behind these references with the expression a is b. This expression is equivalent to id(a) == id(b). So, it evaluates to True if a and b are the same object (they occupy the same memory address in CPython). Otherwise, it is evaluated to be False.

The is not operator is the negation of the is operator. So, the expression a is not b is equivalent to id(a) != id(b). Therefore, it evaluates to True if a and b are distinct objects (they occupy distinct memory addresses in CPython). Otherwise, it is evaluated to be False.

I hope you found this article helpful. Anyway, thank you very much for reading, and see you again next time!

Web App Reverse Checklist

Ready to Build Your Next Web App?

Get my Web App Reverse Checklist first ...


Software Engineering is often driven by fashion, but swimming with the current is rarely the best choice. In addition to knowing what to do, it's equally important to know what not to do. And this is precisely what my free Web App Reverse Checklist will help you with.

Subscribe below to get your free copy of my Reverse Checklist delivered to your inbox. Afterward, you can expect one weekly email on building resilient Web Applications using Python, JavaScript, and PostgreSQL.

By the way, it goes without saying that I'm not sharing your email address with anyone, and you're free to unsubscribe at any time. No spam. No commitments. No questions asked.

Continue Reading?

Here are a few more Articles for you ...


The Built-In callable() Function

Learn about the callable() function in Python. This article explains how everything in Python is potentially callable, including classes and instances.

By Christoph Schiessl on Python

Comparing Strings using Levenshtein Distance

Learn about the Levenshtein distance algorithm, a popular and easy-to-implement way to measure the similarity between two strings.

By Christoph Schiessl on Python

The Built-In bool() Class

Learn about boolean values in Python and the standard truth testing procedure. Understand how objects are converted to True or False.

By Christoph Schiessl on Python

Christoph Schiessl

Hi, I'm Christoph Schiessl.

I help you build robust and fast Web Applications.


I'm available for hire as a freelance web developer, so you can take advantage of my more than a decade of experience working on many projects across several industries. Most of my clients are building web-based SaaS applications in a B2B context and depend on my expertise in various capacities.

More often than not, my involvement includes hands-on development work using technologies like Python, JavaScript, and PostgreSQL. Furthermore, if you already have an established team, I can support you as a technical product manager with a passion for simplifying complex processes. Lastly, I'm an avid writer and educator who takes pride in breaking technical concepts down into the simplest possible terms.