Identity and membership operators in Python answer two specific questions that come up in nearly every real program. Identity operators tell you whether two variables point to the exact same object in memory, which matters when you need to distinguish between two separate copies of the same data and one object referenced by two names. Membership operators tell you whether a value exists inside a collection, which is how you check if a username is in a list of allowed users, whether a substring appears in a larger string, or whether a dictionary contains a given key. These two operator families share the same precedence level as the comparison operators covered earlier, and they are the last piece of the puzzle before you move into control flow.
This article ties together the identity concepts introduced in the earlier article on comparison operators in Python and the membership testing previewed in Python collections explained. Identity and membership do not replace comparison or arithmetic. They solve different problems, and knowing which tool to use for each problem is what separates code that works from code that is correct and fast.
Identity operators: is and is not
The is operator checks whether two variables refer to the same object in memory. It does not check whether two objects have the same value. Two separate lists that both contain the numbers one, two, and three are equal according to the equality operator because their contents match, but they are not the same object according to the is operator because each list was created independently and occupies a different location in memory. Python assigns every object a unique integer identifier that you can inspect with the built-in id function, and the is operator effectively checks whether two variables have the same id.
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True (same contents)
print(a is b) # False (different objects)
print(a is c) # True (c points to the same list as a)The primary use of the is operator in everyday Python is comparing a value to None. Writing an identity check against None is both the idiomatic and the recommended approach because None is a singleton, meaning only one None object ever exists in a running Python program. Every variable set to None points to that same object, so the identity check always gives the correct answer. The equality operator also works for None in practice, but the identity operator is faster and cannot be overridden by a custom equality method on some other object that happens to behave like None.
Python also uses the is operator internally in an optimization called interning. Small integers and short strings are cached and reused, so two separate assignments of the same small integer may happen to return True for an identity check. Relying on this behavior is a mistake. The interpreter is free to change which values are interned between versions, and code that depends on identity comparisons for numbers or strings will break silently. Use equality for values and reserve identity for checking against singletons like None, True, and False.
Membership operators: in and not in
The in operator checks whether a value exists inside a container and returns True or False. It works across every built-in collection type but with slightly different semantics for each. For strings, in checks whether the left operand is a substring of the right operand. For lists, tuples, sets, and ranges, in checks whether the left operand is an element. For dictionaries, in checks whether the left operand is a key, not a value. The not in operator returns the opposite boolean result.
print("py" in "python") # True (substring)
print(3 in [1, 2, 3, 4]) # True (element)
print("name" in {"name": "Maya", "age": 25}) # True (key)
print("Maya" in {"name": "Maya"}) # False (checks keys, not values)The performance of in depends on the container type. For lists and tuples, Python scans each element from the beginning until it finds a match or reaches the end. The time this takes grows linearly with the size of the collection. For sets and dictionaries, Python uses a hash table internally, which means the membership test finishes in roughly the same amount of time regardless of whether the collection has ten items or ten million. When your program repeatedly checks membership against a large collection, storing the values in a set instead of a list can make the difference between a program that finishes instantly and one that times out.
The membership operator also works with the range type, which is efficient because Python computes the answer mathematically rather than generating every number. Checking whether a value falls within a range does not create a list of all the numbers in between. Python simply verifies that the value is within the start and stop bounds and that it aligns with the step value if one is specified.
How identity and membership relate
Identity and membership operators share the same precedence level as comparison operators and participate in the same chaining rules. You can write an expression that chains membership, identity, and comparison operators together, and Python will evaluate each adjacent pair with an implicit and between them. The expression checking whether a value is in a list and also not None can be written as a single chained condition.
The combination of membership with logical operators from the earlier article on logical operators in Python produces some of the most common patterns in Python code. Checking whether a collection is not empty and then testing membership is a safe guard pattern that prevents errors. Writing a membership test on the right side of an or operator provides a clean way to check multiple possible containers.
Membership testing also connects to the truthiness rules covered in the logical operators article. An empty container is falsy, so testing a container directly in an if-statement checks whether it has any elements. Adding a membership test on top of that checks whether a specific element is one of those elements. These two checks together are the foundation of input validation, access control, and data filtering patterns that appear in every Python program beyond the tutorial stage.
Rune AI
Key Insights
- Identity operators is and is not compare object identity in memory, not value equality.
- Use is for comparing to None and for checking whether two variables reference the same object.
- Membership operators in and not in check whether a value exists inside a string, list, tuple, set, or dictionary.
- For dictionaries, in checks keys, not values.
- Membership testing in sets and dictionaries runs in constant time and is far faster than looping for large collections.
Frequently Asked Questions
What is the difference between `is` and `==` in Python?
When should I use `in` instead of a loop?
Does `in` work with all Python collection types?
Conclusion
Identity operators tell you whether two names point to the same object, and membership operators tell you whether a value lives inside a collection. Both are small in syntax but large in the bugs they prevent when used correctly.
More in this topic
Nested Lists in Python
Learn how to create, access, and modify nested lists in Python. Build grids and matrices, and understand how shallow copies affect multi-dimensional data.
List Comprehensions in Python
Master Python list comprehensions to create, filter, and transform lists in a single line. Learn the syntax, common patterns, and when to use a regular loop instead.
Copy Python Lists
Learn how to copy Python lists using slicing, the copy method, the list constructor, and the copy module. Understand shallow vs deep copies.