Identity Operators

Code Examples

Example 1

The is operator checks if two variables refer to the same object in memory. Even though a and b contain the same values, they are different objects (different memory locations), so a is b returns False. However, since c was assigned to a, they reference the same object, so a is c returns True. The id() function shows the unique identity of each object.

# Basic usage of 'is'
a = [1, 2, 3]
b = [1, 2, 3]
c = a  # c refers to the same list object as a

print(a == b)  # Output: True (same values)
print(a is b)  # Output: False (different objects in memory)
print(a is c)  # Output: True (same object in memory)

# Visualizing object IDs
print(id(a))   # Output: 140275201088960 (this number will vary on your system)
print(id(b))   # Output: 140275201088512 (different from a's ID)
print(id(c))   # Output: 140275201088960 (same as a's ID)

Example 2

The is not operator is the inverse of is. It returns True if the variables refer to different objects in memory and False if they refer to the same object. This is useful when you need to ensure that two variables do not reference the same object.

# Basic usage of 'is not'
x = [4, 5, 6]
y = [4, 5, 6]
z = x

print(x is not y)  # Output: True (different objects)
print(x is not z)  # Output: False (same object)

# Checking if variables refer to different objects
original_list = [1, 2, 3]
new_list = [1, 2, 3]
are_different_objects = original_list is not new_list
print(are_different_objects)  # Output: True

Example 3

A common mistake is using is to compare values when == should be used. Use == to check if two objects have the same value, and use is only when you need to check if two variables reference the exact same object. For basic types like integers outside the small range, strings with special characters, or any mutable objects, is behavior may be unexpected.

# Equality vs Identity
a = [1, 2, 3]
b = [1, 2, 3]

# Correct usage
print(a == b)  # Output: True (values are equal)
print(a is b)  # Output: False (different objects)

# Common mistake with values
x = 1000
y = 1000
print(x == y)  # Output: True (values are equal)
print(x is y)  # Output: May vary, but relying on this is a mistake

# Correct choices for different scenarios
same_value = a == b       # Checking if contents are the same
same_object = a is b      # Checking if they're the exact same object

Example 4

When copying objects, understanding identity is crucial. A reference points to the same object, while a shallow copy creates a new object but doesn't copy nested objects. The is operator helps verify whether you're working with the same object or a copy, which is especially important when modifying nested data structures.

# Shallow copy vs. reference
original = [1, 2, [3, 4]]
reference = original              # Just another reference to the same object
shallow_copy = original.copy()    # Creates a new list with the same elements

print(original is reference)      # Output: True (same object)
print(original is shallow_copy)   # Output: False (different objects)

# But nested objects are still the same
print(original[2] is shallow_copy[2])  # Output: True (nested list is the same object)

# Modifying the nested list affects both
original[2][0] = 99
print(shallow_copy[2])  # Output: [99, 4] (affected by the change to original)