DEV Community

Samuel Ochaba
Samuel Ochaba

Posted on

"is" vs "==": The Python Operator That Trips Up Beginners

The Bug That Wastes Hours

Here's a debugging horror story I've seen play out dozens of times: a developer spends 30 minutes tracking down a bug, only to discover that their "equal" lists aren't actually equal—at least not in the way Python sees it.

The culprit? Confusing is with ==.

This single misunderstanding causes more late-night debugging sessions than almost any other Python concept. Let's fix that forever.

Prerequisites

Before diving in, you should understand:

  • Basic Python syntax
  • What variables are and how assignment works
  • The concept of objects in Python

The Core Distinction

Python gives you two ways to check if things are "the same":

Operator Checks Question it answers
== Value Do these have the same content?
is Identity Are these literally the same object in memory?

Let's see the trap in action:

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

print(a == b)  # True - same values
print(a is b)  # False - different objects!
Enter fullscreen mode Exit fullscreen mode

Both lists contain [1, 2, 3], so they're equal in value. But Python created two separate list objects at two different memory addresses. They're twins, not the same person.

When This Actually Breaks Your Code

Here's a real-world scenario. Imagine you're caching API responses:

cached_result = None

def get_data():
    global cached_result
    if cached_result is []:  # BUG! This will never be True
        return cached_result
    # ... fetch data ...
Enter fullscreen mode Exit fullscreen mode

That is [] check will always fail because each [] creates a new list object. The condition should use == or, better yet, check for truthiness.

The Rule That Will Save You

Memorize this:

Use Case Operator
Checking for None is
Everything else ==
# Correct: use 'is' for None
if result is None:
    handle_missing_data()

# Correct: use '==' for values
if user_input == "quit":
    break

# Correct: use '==' for list comparison
if current_list == expected_list:
    print("Match!")
Enter fullscreen mode Exit fullscreen mode

Why is for None?

None is special in Python—it's a singleton. There's only ever one None object in the entire Python runtime. When you write None, you're always referring to that exact same object.

This means is None is:

  1. Semantically correct - You're asking "is this the None object?"
  2. Slightly faster - Identity checks are quicker than equality checks
  3. PEP 8 recommended - It's the official Python style guide's preference

Bonus: Short-Circuit Evaluation

While we're talking about operators, here's another powerful concept. Python is lazy—it won't evaluate what it doesn't need to:

x = 0
result = x != 0 and (10 / x) > 5
print(result)  # False, no ZeroDivisionError!
Enter fullscreen mode Exit fullscreen mode

Python sees that x != 0 is False. Since False and anything is always False, it skips the division entirely.

You can use this intentionally:

# Clean default value pattern
username = input("Name: ") or "Guest"
Enter fullscreen mode Exit fullscreen mode

If the user enters nothing (empty string is falsy), Python short-circuits and uses "Guest".

Common Mistakes to Avoid

  1. Using is to compare strings or numbers - It might work sometimes due to Python's caching, but it's unreliable and wrong
  2. Using is to compare lists or dicts - Almost always a bug
  3. Forgetting that is not exists - Use if x is not None: instead of if not x is None:
  4. Assuming == and is are interchangeable - They fundamentally check different things

Quick Reference

# IDENTITY (is) - Same object?
x is None          # ✓ Correct
x is True          # ✓ Correct (True is also a singleton)
a is b             # Rarely what you want for other types

# EQUALITY (==) - Same value?
name == "Alice"    # ✓ Correct
count == 0         # ✓ Correct
list1 == list2     # ✓ Correct
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. == checks value (do these contain the same data?)
  2. is checks identity (are these the exact same object?)
  3. Use is for None checks, == for everything else
  4. Short-circuit evaluation with and/or can prevent errors and create elegant defaults
  5. When in doubt, use ==—it's almost always what you want

What's Next?

Understanding the difference between identity and equality is fundamental to writing correct Python code. It's one of those concepts that separates beginners from practitioners.

This article is adapted from "Zero to AI Engineer: Python Foundations." I'm writing this book in public—subscribe on Substack to follow along and get notified at launch.

If this helped you, drop a 🧡 and share it with someone learning Python!


Top comments (2)

Collapse
 
a-k-0047 profile image
ak0047

Really clear and beginner friendly article — thank you!

Collapse
 
samuel_ochaba_eb9c875fa89 profile image
Samuel Ochaba

Thank you! That's exactly the goal—making these "gotcha" concepts click before they cause debugging headaches. Glad it landed well. 🙏