# Python Identity and Membership Operators: is and in

Source: https://devdocs10.com/articles/python/python-identity-membership  
By Murat Bo · Published 2026-11-08 · DevDocs10 (https://devdocs10.com)

Python's `is` operator checks whether two names point to the same object, and `in` checks whether a value is a member of a container. They are not the same as `==`, which compares values, or as looping by hand through a collection. This article shows how both operators work, when to use them, and the mistakes that trip people up.

> **Difficulty:** Beginner
>
> **Helpful to know first:** basic variables, Python values and objects, and how lists, tuples, strings, sets, and dictionaries store data.

## How Python Decides Whether Two Names Refer to the Same Object

`is` answers a very specific question: do these two references point to the exact same object in memory? That is why it is called an identity operator. It does not ask whether two objects have the same value; it asks whether they are the same object.

Here is the smallest useful example:

```python
a = [1, 2, 3]
b = a

print(a is b)
print(a == b)
# Output:
# True
# True
```

Both lines are `True` because `b` refers to the same list object as `a`. The list has one identity, and both names point to it.

If you create a second list with the same contents, the values can still match while the objects are different:

```python
a = [1, 2, 3]
b = [1, 2, 3]

print(a is b)
print(a == b)
# Output:
# False
# True
```

That distinction matters when you care about object identity, not just equal values. Most of the time, you compare values with `==` and reserve `is` for special cases such as checking for `None`.

## How Python Checks Whether an Item Is Inside a Container

`in` asks whether a container holds a value. Python uses the container's own membership rules, so the meaning depends on the type on the right side. For sequences like lists and tuples, Python checks items one by one. For strings, it checks for substrings. For sets and dictionaries, membership is optimized for fast lookups.

These examples show the most common cases:

```python
print(3 in [1, 2, 3])
print("cat" in "education")
print("name" in {"name": "Ava", "age": 12})
# Output:
# True
# False
# True
```

For the dictionary, `in` checks keys, not values. That surprises many beginners. The expression `"Ava" in {"name": "Ava", "age": 12}` would be `False` because `"Ava"` is a value, not a key.

## Working Examples of is and in in Real Python Code

### Checking for None the right way

Python programmers use `is None` because `None` is a singleton object. There is only one `None` in a program, so identity comparison is the correct tool.

```python
def find_user(users, name):
    for user in users:
        if user == name:
            return user
    return None

result = find_user(["Maya", "Noah"], "Iris")
print(result is None)
# Output:
# True
```

If you wrote `== None`, the code would often work, but it is less precise and can behave badly with custom classes that define unusual equality rules.

### Finding whether a value exists before using it

`in` often replaces a longer loop. That makes code easier to read and usually faster because Python already knows how to test membership for many built-in containers.

```python
inventory = ["pencil", "notebook", "eraser"]

if "notebook" in inventory:
    print("You have a notebook.")
else:
    print("Notebook missing.")
# Output:
# You have a notebook.
```

The same logic written by hand would need a loop, a flag, and more room for mistakes. The membership operator does exactly what the code says.

### Using membership with dictionaries and sets

Membership is especially useful with dictionaries and sets because these types are designed for fast lookups.

```python
scores = {"Ana": 91, "Omar": 88, "Lea": 95}
tags = {"python", "learning", "operators"}

print("Omar" in scores)
print(95 in scores)
print("python" in tags)
# Output:
# True
# False
# True
```

For `scores`, the key `"Omar"` is present, but the value `95` is not a key, so the second line is `False`. A set contains only values, so membership checks the elements directly.

### Testing whether two variables point to the same mutable object

Identity matters when two names may share one mutable object. If one name changes the object, the other name sees that same change because both names point to the same object.

```python
first = [10, 20]
second = first
second.append(30)

print(first)
print(first is second)
# Output:
# [10, 20, 30]
# True
```

This is aliasing, not copying. Both names refer to one list object, so changes through one name show up through the other.

## How is and in Behave in Detail

`is` compares identity, not value. That means it can only be `True` when both operands are the same object. Python may reuse some small integers or strings in an implementation detail, but you should never depend on that behavior for program logic. The safe rule is simple: use `is` for singleton checks like `None`, and use `==` for value comparison.

`in` calls a container's membership logic. For a list or tuple, Python checks items one at a time until it finds a match or reaches the end. For a string, it searches for a substring. For a dictionary, it checks keys. For a set, membership is designed to be fast because sets are built for this exact job.

> A useful memory aid: `is` means same object, `in` means found inside.

There is one more detail beginners often miss: `in` works with any object that supports membership testing, including custom classes that define the right method. That is why the exact behavior depends on the container type.

## Predict the Output

These short examples test the two most common misunderstandings: aliasing with `is` and dictionary membership with `in`.

### Alias or copy?

What does this print?

```python
items = [1, 2]
other = items
other[0] = 99

print(items)
print(items is other)
```

**Answer:**

The list is changed through `other`, so both names show the updated value. They still refer to the same object.

```bash
# Output:
# [99, 2]
# True
```

`other = items` does not make a copy. It creates a second reference to the same list.

### Dictionary values versus keys

What does this print?

```python
data = {"a": 1, "b": 2}

print(2 in data)
print("b" in data)
```

**Answer:**

Dictionary membership checks keys, not values. The key `"b"` is present, but the value `2` is not checked by `in`.

```bash
# Output:
# False
# True
```

## Common Mistakes with is and in

### Using is to compare values instead of identities

Beginners often write `is` when they mean `==`. The code may appear to work for small examples, but it is not reliable for value comparison.

**Problem:** This code asks whether two strings have the same value, but `is` checks whether they are the same object.

```python
name = "Py" + "thon"
if name is "Python":
    print("Matched")
```

**Fix:** Use `==` when you want equal values.

```python
name = "Py" + "thon"
if name == "Python":
    print("Matched")
```

The fixed version works because it compares the contents of the strings.

### Checking dictionary values with in and getting the wrong answer

Dictionary membership checks keys only. If you want to test values, you need to look at `.values()`.

**Problem:** This code expects `in` to find a dictionary value, but it only checks the keys.

```python
grades = {"Ava": 90, "Ben": 85}
if 90 in grades:
    print("Found")
```

**Fix:** Test the values view when you want values, not keys.

```python
grades = {"Ava": 90, "Ben": 85}
if 90 in grades.values():
    print("Found")
```

The corrected version works because `grades.values()` exposes the dictionary values for membership testing.

### Using in on the wrong type

The right side of `in` must be a container or an object that supports membership testing. If it is not, Python raises a `TypeError`.

**Problem:** This code tries to use membership on an integer, which is not iterable.

```python
count = 5
if 1 in count:
    print("Found")
# TypeError: argument of type 'int' is not iterable
```

**Fix:** Use `in` with a list, string, set, tuple, dictionary, or another supported container.

```python
count = [5]
if 1 in count:
    print("Found")
else:
    print("Not found")
```

The fixed version works because the right side is now a list, so Python can check membership.

## When to Use is, and When to Use Something Else

| Use this | When you want to know | Example |
| --- | --- | --- |
| `is` | whether two names refer to the same object | `value is None` |
| `==` | whether two objects have equal values | `a == b` |
| `in` | whether a value exists inside a container | `needle in haystack` |

Use `is` for singletons such as `None`, and use `==` for normal value comparison. Use `in` when you want Python to search a sequence, string, set, or dictionary keys for you. If you need to check dictionary values, use `.values()`; if you need keys, the plain dictionary is enough.

> A practical rule: if you are asking "same object?" use `is`. If you are asking "same value?" use `==`. If you are asking "contained here?" use `in`.

## Common Interview Questions About is and in

### Why is None compared with is instead of ==?

`None` is a singleton, so identity comparison is the clearest and safest way to check for it. It avoids confusion with classes that customize equality.

### Does in check dictionary keys or values?

It checks keys. Use `dictionary.values()` if you need to search values, or `dictionary.items()` if you want to search key-value pairs.

### Is is faster than ==?

`is` is usually a very simple pointer comparison, so it can be faster, but speed is not the main reason to use it. The main reason is correctness: identity and equality answer different questions.

## Try It Yourself

Write a small program that:

- stores a list of colors,
- checks whether `"blue"` is in the list,
- creates two names that point to the same list,
- prints whether the two names use `is` to point to the same object.

Expected output:

```python
True
True
```

Hint: assign one variable to the other to make an alias, not a copy.

**Solution:**

```python
colors = ["red", "blue", "green"]
print("blue" in colors)

first_list = colors
second_list = first_list
print(first_list is second_list)
```

## Summary

- `is` checks identity, not value.
- `==` checks whether two objects have equal values.
- `in` checks whether a value is inside a container.
- Dictionary membership checks keys, not values.
- Use `is None` for singleton checks.
- Use `==` for normal comparisons and `in` for membership tests.

Next, study Python's equality operators and how they differ from identity operators so you can choose the right comparison every time.
