Python
string-comparison
is-vs-equals
programming
duplicates

String comparison in Python is vs.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Python has two comparison operators that beginners often confuse: == checks value equality (do two objects have the same content?), while is checks identity (are two variables the same object in memory?). For strings, == is almost always the correct choice. Using is for string comparison can appear to work due to Python's string interning optimization, but it is unreliable and can produce bugs that only appear in certain contexts.

The Difference: == vs is

python
1a = "hello"
2b = "hello"
3
4# Value equality — checks if contents are the same
5print(a == b)  # True
6
7# Identity — checks if they are the exact same object in memory
8print(a is b)  # True (due to string interning — but DON'T rely on this!)

When They Diverge

python
1a = "hello world"
2b = "hello" + " " + "world"
3
4print(a == b)   # True — same content
5print(a is b)   # False — different objects in memory
6
7# Another example
8a = "hello!"
9b = "hello!"
10print(a == b)   # True
11print(a is b)   # False (may be True in some Python implementations, not guaranteed)

Why is Sometimes Works for Strings

Python interns (caches and reuses) certain strings to save memory:

python
1# Short strings that look like identifiers are interned
2a = "hello"
3b = "hello"
4print(a is b)  # True — Python reuses the same object
5
6# Strings with spaces, punctuation, or special characters are NOT always interned
7a = "hello world"
8b = "hello world"
9print(a is b)  # May be True or False — implementation-dependent!
10
11# Compile-time constants may be interned
12a = "hello" + "world"  # Computed at compile time
13b = "helloworld"
14print(a is b)  # True in CPython — both are compile-time constants
15
16# Runtime-computed strings are NOT interned
17x = "world"
18a = "hello" + x  # Computed at runtime
19b = "helloworld"
20print(a is b)  # False

Interning Rules (CPython)

CPython interns strings that:

  • Are compile-time constants
  • Contain only ASCII letters, digits, and underscores
  • Are used as variable names, function names, or attributes
  • Are explicitly interned with sys.intern()

These rules are implementation details and may differ in PyPy, Jython, or future Python versions.

When to Use Each

OperatorUse forExample
==Comparing string contentif name == "admin":
isChecking for Noneif x is None:
isChecking for sentinel objectsif result is MISSING:
is notChecking not Noneif x is not None:
python
1# CORRECT: Use == for string comparison
2username = get_username()
3if username == "admin":
4    grant_access()
5
6# CORRECT: Use is for None checks
7result = find_user("alice")
8if result is None:
9    print("User not found")
10
11# WRONG: Using is for string comparison
12if username is "admin":  # Unreliable!
13    grant_access()

The id() Function

id() returns the memory address of an object. a is b is equivalent to id(a) == id(b):

python
1a = "hello"
2b = "hello"
3print(id(a))       # 140234567890 (example address)
4print(id(b))       # 140234567890 (same — interned)
5print(a is b)      # True
6print(id(a) == id(b))  # True
7
8c = "hello world"
9d = "hello world"
10print(id(c))       # 140234567990
11print(id(d))       # 140234568090 (different — not interned)
12print(c is d)      # False

Explicit String Interning

Use sys.intern() to force interning for performance-critical lookups:

python
1import sys
2
3# Intern strings for fast identity comparison
4a = sys.intern("hello world")
5b = sys.intern("hello world")
6print(a is b)  # True — both point to the same interned string
7
8# Use case: dictionary keys in a large dataset
9# Interning reduces memory and speeds up key lookups
10keys = [sys.intern(key) for key in raw_keys]

sys.intern() is useful when you have millions of repeated strings (like column names, tags, or tokens) and want to save memory and speed up comparisons.

Common String Comparison Operations

python
1# Case-insensitive comparison
2if name.lower() == "admin":
3    print("Welcome, admin")
4
5# Prefix/suffix checking
6if filename.startswith("."):
7    print("Hidden file")
8if filename.endswith(".py"):
9    print("Python file")
10
11# Substring check
12if "error" in log_line:
13    print("Error found")
14
15# Compare with multiple values
16if status in ("active", "pending", "trial"):
17    allow_access()

Python Linting Warnings

Modern linters warn about using is with string literals:

python
1# Pylint: W0123 (comparison-with-callable)
2# Flake8: E711 (comparison to None)
3
4if name is "admin":  # SyntaxWarning in Python 3.8+
5    pass
6# SyntaxWarning: "is" with a literal. Did you mean "=="?

Starting with Python 3.8, using is or is not with string, integer, or float literals produces a SyntaxWarning.

Common Pitfalls

  • Relying on is for strings: is may work for short, simple strings due to interning, but fail for dynamically constructed strings. Always use == for content comparison.
  • Integer interning confusion: Like strings, Python caches small integers (-5 to 256). a = 256; b = 256; a is b is True, but a = 257; b = 257; a is b is False. Same trap as string interning.
  • Mutable objects and is: For lists, dicts, and other mutable objects, is checks if they are the same instance: a = [1]; b = [1]; a == b is True but a is b is False. This is the correct behavior.
  • is None is correct: None is a singleton — there is only one None object in Python. Using is None is correct and recommended by PEP 8.
  • Performance myth: While is is slightly faster than == (identity check vs value comparison), the difference is negligible. Do not use is for performance — use it only for identity checks.

Summary

  • Use == to compare string values — this is the correct operator for content comparison
  • Use is only for identity checks: None, sentinel objects, and singleton patterns
  • String interning makes is appear to work for some strings, but this is an implementation detail
  • Python 3.8+ warns when using is with literals: SyntaxWarning: "is" with a literal
  • Use sys.intern() if you explicitly need interned strings for performance in high-volume scenarios

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.