in operator
The in keyword is a membership operator in Python. It checks whether a value exists within a sequence such as a string, list, tuple, set, or dictionary.
Syntax
value in sequence
Returns True if the value is found, False otherwise.
Checking Membership in Different Types
Lists
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits)
# True
print("orange" in fruits)
# False
Tuples
colors = ("red", "green", "blue")
print("red" in colors)
# True
print("yellow" in colors)
# False
Sets
vowels = {"a", "e", "i", "o", "u"}
print("a" in vowels)
# True
print("b" in vowels)
# False
Strings
The in operator checks for substrings:
text = "Hello, World!"
print("Hello" in text)
# True
print("Python" in text)
# False
print("o" in text)
# True
Dictionaries
By default, in checks for keys, not values:
person = {"name": "Alice", "age": 30, "city": "NYC"}
print("name" in person)
# True
print("Alice" in person)
# False
print("age" in person)
# True
To check for values, use .values():
print("Alice" in person.values())
# True
To check for key-value pairs, use .items():
print(("name", "Alice") in person.items())
# True
Using in Conditional Statements
Basic If Statement
user_permissions = ["read", "write", "delete"]
if "delete" in user_permissions:
print("Can delete files")
# Can delete files
Not In
Use not in to check absence:
banned_users = ["alice", "bob", "charlie"]
user = "dave"
if user not in banned_users:
print("Access granted")
# Access granted
Checking Environment Variables
import os
if "PYTHONPATH" in os.environ:
print(f"Python path: {os.environ['PYTHONPATH']}")
Performance Characteristics
Sets and Dictionaries: O(1) Average
Looking up membership in sets and dictionaries is very fast:
allowed_ids = {1, 2, 3, 4, 5}
# Fast - O(1) average case
print(3 in allowed_ids)
# True
Lists and Tuples: O(n)
Linear search through lists is slower for large collections:
names = ["alice", "bob", "charlie", "dave"]
# Slower for large lists - O(n)
print("charlie" in names)
# True
When to Convert List to Set
If you’re checking membership multiple times, convert to a set first:
# Slow - converts on every check
while user_input:
if user_input in user_list: # O(n) each time
process(user_input)
# Fast - convert once, O(1) each check
user_set = set(user_list)
while user_input:
if user_input in user_set: # O(1) each time
process(user_input)
in with Range
The in keyword also works with range() objects:
print(5 in range(10))
# True
print(10 in range(10))
# False
print(0 in range(-5, 5))
# True
in with Generators and Iterators
You can check membership in any iterable using a generator expression:
import itertools
# Check if any number greater than 10 exists
numbers = [1, 5, 8, 3, 9]
has_large = any(n > 10 for n in numbers)
print(has_large)
# False
# But note: in doesn't work with generators directly
# gen = (n for n in numbers)
# print(5 in gen) # This would consume the generator
Comparison with Other Languages
Python’s in is similar to .includes() in JavaScript:
# Python
"a" in "abc" # True
"a" in ["a", "b", "c"] # True
// JavaScript
"abc".includes("a") // true
["a", "b", "c"].includes("a") // true
In SQL, similar functionality uses IN and LIKE:
-- SQL equivalent
SELECT * FROM users WHERE role IN ('admin', 'moderator');
Common Patterns
Validate User Input
valid_choices = {"yes", "no", "maybe"}
choice = input("Enter choice: ").lower()
if choice in valid_choices:
print(f"You chose: {choice}")
else:
print("Invalid choice")
Check Feature Flags
enabled_features = {"dark-mode", "notifications", "beta"}
if "beta" in enabled_features:
enable_beta_ui()
Safe Dictionary Access
config = {"host": "localhost", "port": 8080}
# Use in to avoid KeyError
if "timeout" in config:
print(f"Timeout: {config['timeout']}")
else:
print("Using default timeout")
See Also
- not keyword — logical negation
- for keyword — iterate over sequences
- set types — efficient membership testing
- dictionary methods — safe dictionary access