Tech With Galvan

Membership & Identity: in, is

15 min • Beginner • Module 4

Check what's inside what — and the is-vs-== trap everyone falls into.

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

  • in on a dict returns True unexpectedly — it checks keys, not values. For values: "Aarav" in student.values().
  • x is 5 works but is wrong — it happens to pass for small numbers; use == for values.
  • TypeError using in on a number — 5 in 12345 is meaningless; in needs a collection or string on the right.

✅ Checkpoint

  1. What does "py" in "python" return? (True)
  2. For a dict d, does "x" in d check keys or values? (Keys)
  3. a = [1]; b = [1] — a == b? a is b? (True, False)
  4. 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.