Skip to content

Python Identity and Membership Operators

Updated 6 min read Aimerscrew

Python identity and membership operators answer two everyday questions. "Are these the exact same thing?" is answered by is. "Is this inside that?" is answered by in. In this lesson, you'll learn how is, is not, in and not in work, why you should write x is None, and why is is the wrong tool for comparing numbers and text.

🌍 Real-life example

Two hotel guests each have a key card for "Room 512". Are the cards equal? Yes, they open the same door. Are they the same card? No, there are two physical cards. That's the difference between == (equal value) and is (same object). And when the receptionist checks whether your name is on the guest list, that's in.

What are identity operators in Python?

Every value in Python lives in memory as an object. A variable is a name that points to an object, as you saw in Python variables. Identity operators check whether two names point to the same object, not just to equal values.

OperatorMeaningExample
isTrue if both sides are the same objectx is None
is notTrue if they are different objectsx is not None
Left: names a and b both point to one object, so a is b is True. Middle: a and c point to two separate objects with equal values, so a == c is True but a is c is False. Right: in checks whether a value is inside a collection
is asks "same object?", == asks "equal value?" and in asks "is it inside?"

What is the difference between is and == in Python?

== compares values. is compares identity. Here are two shopping lists with the same items. (Lists hold several values in square brackets; you'll learn them in Python lists.)

my_list = ["eggs", "milk"]
your_list = ["eggs", "milk"]
same_list = my_list

print(my_list == your_list)   # same items?
print(my_list is your_list)   # same object?
print(my_list is same_list)
True
False
True

my_list and your_list are two separate lists that happen to contain the same items. same_list = my_list doesn't copy anything; it just puts a second name on the same list. You can see an object's identity number with the built-in id() function: two names are the same object exactly when their id() values match.

Why should you write x is None?

None is Python's special value for "nothing" or "no value yet". There is only one None object in the whole program, so checking identity is exact and fast. The official Python style guide (PEP 8) says to always compare with None using is or is not:

delivery_date = None   # not scheduled yet

print(delivery_date is None)
print(delivery_date is not None)

delivery_date = "Friday"
print(delivery_date is not None)
True
False
True

💡 Tip

Write x is not None, not not x is None. Both work, but is not reads like plain English and is the standard style.

Why shouldn't you use is to compare numbers or strings?

Because two equal numbers or strings are not guaranteed to be the same object. Sometimes Python reuses objects to save memory (it keeps one copy of small integers from -5 to 256, for example), and sometimes it doesn't. That makes is give results that seem random:

order_id = 1000
typed_id = int("1000")   # same value, built at run time

print(order_id == typed_id)
print(order_id is typed_id)
True
False

The values are equal, but they are two different objects. If your code used is here, a correct order number would be rejected. Python even warns you when you write is with a literal number or string:

x = 5
print(x is 5)   # SyntaxWarning: "is" with 'int' literal. Did you mean "=="?

⚠️ Be careful

Rule of thumb: use == to compare values (numbers, strings, lists). Use is only for None, and occasionally True/False or when you truly need "the same object".

What are membership operators in Python?

Membership operators check whether a value is inside a collection, such as a string, a list or a dictionary. They return True or False.

OperatorMeaningExampleResult
inTrue if the value is found"a" in "cat"True
not inTrue if the value is not found"z" not in "cat"True

How do you check if text is in a string?

With strings, in looks for a substring: a piece of text that appears anywhere inside, in the exact same order and case.

email = "maya.lopez@example.com"

print("@" in email)
print("example" in email)
print("Maya" in email)          # case matters
print(" " not in email)         # no spaces allowed
True
True
False
True

How do you check if an item is in a list?

With a list, in checks whether any item is equal to the value (it uses ==, not is). Unlike strings, it matches whole items only:

playlist = ["Yellow", "Dreams", "Africa"]

print("Africa" in playlist)
print("Afr" in playlist)        # not a whole item
print("Hello" not in playlist)
True
False
True

How does in work with a dictionary?

A dictionary stores pairs of keys and values, like a menu of items and prices. You'll learn dictionaries in Python dictionaries. For now, the important part: in checks the keys, not the values.

menu = {"espresso": 2.5, "latte": 3.8, "mocha": 4.2}

print("latte" in menu)
print("tea" in menu)
print(3.8 in menu)              # 3.8 is a value, not a key
True
False
False

Real-world example: checking a sign-up form

username = "skater_jo"
email = "jo@example.com"
promo_code = None
taken_names = ["admin", "skater_jo", "guest"]

print("Name available:", username not in taken_names)
print("Email looks valid:", "@" in email and "." in email)
print("Promo entered:", promo_code is not None)
Name available: False
Email looks valid: True
Promo entered: False

Common mistakes with identity and membership operators

1. Using is to compare values

As shown above, order_id is typed_id can be False even when the numbers are equal. Use ==.

2. Checking a number inside a string

pin = "4821"
print(4 in pin)
TypeError: 'in <string>' requires string as left operand, not int

To search a string, the left side must be text too: "4" in pin.

3. Expecting in to search dictionary values

3.8 in menu is False because in only looks at keys. You'll see how to search values in dictionary methods.

4. Forgetting that in is case-sensitive

"Paris" in "I love paris" is False. Make both sides lowercase first if case shouldn't matter.

Practice exercise

🏋️ Try it yourself

A flight booking stores seat = None and meal_options = ["veggie", "chicken", "fish"]. A passenger asks for "vegan". Print whether a seat has been chosen yet, whether "vegan" is available, and whether the booking code "BA2490" contains "BA".

Show solution
seat = None
meal_options = ["veggie", "chicken", "fish"]
request = "vegan"
booking_code = "BA2490"

print("Seat chosen:", seat is not None)
print("Meal available:", request in meal_options)
print("British Airways flight:", "BA" in booking_code)
Seat chosen: False
Meal available: False
British Airways flight: True

What's next?

You've now met every kind of Python operator. But what happens when you mix several in one line, like 2 + 3 * 4 ** 2? Find out which runs first in Python operator precedence.

Key takeaways

  • is and is not check identity: whether two names refer to the very same object in memory.
  • == checks whether two values are equal; two equal values can still be different objects.
  • Always compare with None using is or is not, as in x is None.
  • Never use is to compare numbers or strings; the result depends on hidden memory details.
  • in and not in check membership: substrings in strings, whole items in lists, and keys in dictionaries.
  • in is case-sensitive for strings, and the left side must be a string when searching a string.

Frequently asked questions

What is the difference between is and == in Python?

The == operator checks whether two values are equal. The is operator checks whether two names point to the exact same object in memory. Two separate lists with the same items are == but not is.

Why do we use is None instead of == None?

There is only one None object in Python, so is None is an exact and fast identity check. It also cannot be fooled by objects that customize ==. PEP 8 recommends is None and is not None.

How do you check if a substring is in a string in Python?

Use the in operator: "cat" in "concatenate" is True. The check is case-sensitive, so convert both strings to lowercase first if case should not matter.

Does in check keys or values in a Python dictionary?

It checks keys only. To check values, use value in my_dict.values().

Why does a is b sometimes return True for equal numbers?

Python reuses some objects, such as small integers from -5 to 256, to save memory, so equal values may happen to be the same object. This is an implementation detail, so always use == to compare numbers.