Membership & Identity: in, is
Two operators, two different questions: in asks “is this inside that?” and is asks “is this literally that same thing?” Both return booleans, and both are everywhere in real Python.
in — the membership check
email = "[email protected]"
print("@" in email) # True
print("gmail" in email) # False
print("@" not in email) # False — not flips it
Works on strings (substring check), and later on lists, dicts, and more:
languages = ["Python", "Go", "Rust"]
print("Go" in languages) # True
print("Java" in languages) # False
student = {"name": "Aarav", "age": 16}
print("name" in student) # True — checks KEYS in dicts
That last one matters: for dictionaries, in checks keys, not values.
Where in shines: validation
# Password policy
password = input("Password: ")
if "@" in password or "!" in password:
print("Good — contains a special character")
# Email sanity check
email = input("Email: ")
if "@" not in email:
print("That does not look like an email")
You already used in for substring checks in the strings lesson — now you know it is a full operator family with not in as its partner.
is — the identity check
is does not compare values. It asks whether two names point to the same object in memory:
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True — same VALUE
print(a is b) # False — different objects in memory!
print(a is c) # True — same object, two labels
Picture it: a and c are two labels on one box. b is a different box holding identical contents. == compares contents; is compares boxes.
The one place you should use is: None
result = None
if result is None:
print("No result yet")
if result is not None:
print("We have a result")
Checking against None with is is the Python community standard. For everything else — numbers, strings — use ==.
The is-vs-equals trap (why beginners get burned)
Small integers and short strings are cached by Python, which makes is appear to work like ==:
a = 100
b = 100
print(a is b) # True — cached small int, SAME object (implementation detail!)
a = 1000
b = 1000
print(a is b) # Often False in scripts — different objects
Do not rely on that. The rule:
| Comparing | Use |
|---|---|
| Values (numbers, strings, lists) | == / != |
Against None |
is / is not |
| “Is it this exact object?” (rare) | is |
Common Errors & Fixes
inon a dict returns True unexpectedly — it checks keys, not values. For values:"Aarav" in student.values().x is 5works but is wrong — it happens to pass for small numbers; use==for values.TypeErrorusinginon a number —5 in 12345is meaningless;inneeds a collection or string on the right.
✅ Checkpoint
- What does
"py" in "python"return? (True) - For a dict
d, does"x" in dcheck keys or values? (Keys) a = [1]; b = [1]—a == b?a is b? (True, False)- How do you check “result has no value”? (result is None)
Module 4 checkpoint reached — every operator family is now yours. Next: 🧪 Practice, ten quick-fire exercises across all of them.