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!

Ready to Learn More Web Development?

Join my Mailing List to receive 1-2 useful Articles per week.

I send up to two weekly emails on building performant and resilient Web Apps with Python, JavaScript and PostgreSQL. No spam. Unscubscribe at any time.

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

Function Definition with Default Parameters

Learn about Python functions with default parameters. Understand how default parameters work and some essential restrictions and evaluation rules.

By Christoph Schiessl on Python

Extracting all URLs of your sitemap.xml with JavaScript

Learn JavaScript techniques needed to parse your sitemap.xml in order to obtain a list of all pages making up your website.

By Christoph Schiessl on JavaScript

Christoph Schiessl

Christoph Schiessl

Independent Consultant + Full Stack Developer

If you hire me, you can rely on more than a decade of experience, which I have collected working on web applications for many clients across multiple industries. My involvement usually focuses on hands-on development work using various technologies like Python, JavaScript, PostgreSQL, or whichever technology we determine to be the best tool for the job. Furthermore, you can also depend on me in an advisory capacity to make educated technological choices for your backend and frontend teams. Lastly, I can help you transition to or improve your agile development processes.