Python Identity Operators
In this page:
a is b
a is not b
What Is Identity?
Every object in Python lives at a specific memory address, and identity means checking whether two variable names point to that exact same object rather than just holding equal-looking values.
The built-in id() function returns a number representing that address, and Python's is operator compares those addresses directly.
Example: What Is Identity?
a = [1, 2]
b = [1, 2]
print(id(a) == id(b)) # different objects, so different memory addresses
print(a is b) # False, they are equal in value but not identical
is and is not
The is operator returns True only when both operands are literally the same object in memory, while is not is its negation.
This is different from ==, which asks whether two objects have equal value even if they're stored separately — two different list objects with identical contents are equal but not identical.
Example: is and is not
a = [1, 2]
b = a # b now refers to the same list object as a
c = [1, 2] # c is a separate object with equal contents
print(a is b) # True, same object
print(a is not c) # True, different objects
is vs == in Practice
Use == when you care about value equality, like comparing two strings or numbers for content, and reserve is for identity checks such as x is None, which is the idiomatic and recommended way to test for None specifically.
Using == for None comparisons can misbehave with custom classes that override equality.
Example: is vs == in Practice
x = None
print(x is None) # idiomatic identity check for None
print(x == None) # works here too, but is not the recommended style
The Small Integer Cache Gotcha
CPython caches small integers (typically -5 to 256) and short strings as singleton objects for performance, so a = 5; b = 5; a is b often returns True by coincidence, not by design.
Relying on is for general value comparison is a common bug source because this caching behavior isn't guaranteed by the language spec and can vary.
Example: The Small Integer Cache Gotcha
a = 5
b = 5
print(a is b) # True due to CPython's small-int caching, not guaranteed behavior
Practical Identity Checks
Identity checks are most useful for sentinel values, singleton comparisons like is None or is True, and verifying whether two variables reference the exact same mutable object before deciding whether modifying one will affect the other.
This matters especially when passing mutable objects like lists between functions.
Example: Practical Identity Checks
def process(items=None):
if items is None:
items = [] # a new list object is created each call
return items
a = process()
b = process()
print(a is b) # False, each call got its own list object
- Using
isto compare values such asx is 1000orname is "bob"; it tests identity and may beFalseeven when the values are equal (use==). - Being surprised that
a is bisTruefor small ints like5due to caching, then relying on that behaviour. - Using
== Noneinstead of the correctis Nonecheck forNone.
Chapter Quiz — Complete all 16 topics to unlock
0/16 topics done
Complete these topics first:
- Python print()
- Python input()
- Python Format Strings
- Python f-strings
- Python String Formatting
- Python Arithmetic Operators
- Python Relational Operators
- Python Logical Operators
- Python Bitwise Operators
- Python Assignment Operators
- Python Increment & Decrement
- Python Ternary Operator
- Python Operator Precedence
- Python Identity Operators
- Python Membership Operators
- Python Operators