Python > Core Python Basics > Basic Operators > Identity Operators (is, is not)

Identity Operators: `is` and `is not`

This snippet demonstrates the use of identity operators (`is` and `is not`) in Python. These operators check if two variables refer to the same object in memory, not just if they have the same value. Understanding the difference between `==` (equality) and `is` (identity) is crucial for writing efficient and bug-free Python code.

Basic Example

In this example, `x` and `y` are assigned the same list object. Therefore, `x is y` evaluates to `True`. `z` is assigned a *new* list object with the same contents as `x`. Although `x` and `z` have the same values (checked by `x == z`), they are different objects in memory, hence `x is z` evaluates to `False`. `is not` is simply the negation of `is`.

x = [1, 2, 3]
y = x
z = [1, 2, 3]

print(x is y)  # Output: True (x and y point to the same object)
print(x is z)  # Output: False (x and z are different objects with the same value)
print(x == z)  # Output: True (x and z have the same value)

print(x is not y) # Output: False
print(x is not z) # Output: True

Concepts Behind the Snippet

  • Object Identity: Every object in Python has a unique identity, obtained using the `id()` function. The `is` operator compares these identities.
  • Mutability: Mutable objects (like lists and dictionaries) can be modified after creation. If two variables point to the same mutable object, changing one will affect the other.
  • Immutability: Immutable objects (like integers, strings, and tuples) cannot be modified after creation. If two variables appear to point to the same immutable value, Python may optimize memory usage by making them the same object, but this is not guaranteed and should not be relied upon (especially for larger integer values).

Real-Life Use Case

Identity operators are frequently used when checking if a variable is `None`. It is Pythonic and more efficient to write `if my_variable is None:` than `if my_variable == None:`. This is because `is` checks object identity directly, whereas `==` calls the `__eq__` method which could be overridden.

Example with None

This code snippet demonstrates the idiomatic way to check for `None` using the `is` and `is not` operators. Using `is None` is generally preferred over `== None` for readability and performance.

my_variable = None

if my_variable is None:
    print("my_variable is None")

if my_variable is not None:
    print("my_variable is not None") # This will not execute

Best Practices

  • Use `is` and `is not` for identity checks: Use these operators when you need to determine if two variables refer to the exact same object in memory. This is especially important when working with mutable objects or checking for `None`.
  • Use `==` for equality checks: Use the equality operator `==` when you want to compare the *values* of two objects, regardless of whether they are the same object in memory.
  • Avoid relying on `is` for immutable objects unnecessarily: Python might optimize memory by reusing the same object for identical immutable values, but you shouldn't rely on this behavior. Use `==` for comparing values in those cases.

Interview Tip

Be prepared to explain the difference between `==` and `is`. Highlight that `==` checks for equality of values, while `is` checks for identity (i.e., whether two variables point to the same object in memory). Demonstrate your understanding with simple examples involving mutable and immutable objects.

When to Use Them

  • Checking for `None`: As mentioned earlier, `is None` and `is not None` are the preferred ways to check for `None`.
  • Checking for object identity in complex data structures: If you're working with a complex object graph, you might use `is` to verify that two parts of the graph are indeed the same object.
  • Debugging: When debugging, `is` can help you understand if different variables are unexpectedly pointing to the same object, which might be causing unintended side effects.

Memory Footprint

The `is` operator itself has a very low memory footprint as it's a simple pointer comparison. However, incorrect usage of `is` compared to `==` might lead to unintended object duplication which could increase memory usage. For immutable objects Python often reuses the same object for identical values to save memory. However, this behaviour is not guaranteed for all immutable objects or all values. Therefore, it's important to only use `is` when you explicitly want to check for identity.

Alternatives

There are no direct alternatives to `is` and `is not` for checking object identity. The `id()` function can be used to retrieve the object's memory address, but it is rarely used directly in code for comparison. The key is understanding when to use `is` (identity) versus `==` (equality).

Pros

  • Efficiency: `is` is very efficient because it only compares memory addresses.
  • Clarity: Using `is None` is a very clear and Pythonic way to express that you're checking if a variable is `None`.
  • Correctness: In some cases, `is` can avoid subtle bugs that might arise from relying on `==`, especially if the `__eq__` method is overridden.

Cons

  • Misunderstanding: The primary con is misunderstanding the difference between `is` and `==`. Using `is` when you should be using `==` can lead to incorrect behavior.
  • Not suitable for comparing values: `is` should never be used to compare the *values* of two objects. Always use `==` for value comparison.

FAQ

  • What is the difference between `==` and `is`?

    `==` checks if two objects have the same *value*. `is` checks if two variables refer to the *same object in memory* (i.e., they have the same identity).
  • Why is `is None` preferred over `== None`?

    `is None` is preferred because it directly checks if the variable refers to the `None` object itself. `== None` calls the `__eq__` method, which could be overridden by a custom class, potentially leading to unexpected results. `is None` is also generally faster.
  • Can `is` be used to compare strings?

    While it might sometimes work for small string literals due to Python's string interning, you should **never** rely on `is` for string comparison. Always use `==` to compare string values. String interning is an optimization that may or may not be applied, and it is not guaranteed.