Look at this Python code and try to guess the output:
a = 256
b = 256
c = 1000
d = 1000
print(a is b) # Line 1
print(c is d) # Line 2
print([1, 2, 3] == [1, 2, 3]) # Line 3
print([1, 2, 3] is [1, 2, 3]) # Line 4What do you think the program prints?
- Will all four lines be
True? - Maybe
Truefor numbers butFalsefor lists? - Or something else entirely?
If you’re not 100% sure, don’t worry — you’re not alone. Many Python developers (even experienced ones) get tripped up by this.
If you can’t confidently explain the output, then you must keep reading. This post will finally make the difference between is and == crystal clear.
Key Concept
At first glance, they seem similar. But as you’ll see, the difference can lead to some very tricky and confuse situations.
==(Equality Operator): Compares values.is(Identity Operator): Compares object identity in memory.
Numbers Comparsion
a = 1000
b = 1000
print(a == b) # True
print(a is b) # Falsea == bis True, because both values are1000.a is bis False, because Python created two different integer objects in memory.
But with smaller numbers, you get a surprise:
x = 100
y = 100
print(x == y) # True
print(x is y) # True (small integers are cached!)- Python caches integers between -5 and 256 for performance. That’s why sometimes
isreturns True for numbers, and sometimes not.
String Comparsion
Strings behave similarly as Numbers.
s1 = "henry"
s2 = "henry"
s3 = "henryc48.sg-host.com"
s4 = "henryc48.sg-host.com"
print(s1 == s2) # True
print(s1 is s2) # True (string interning)
print(s3 == s4) # True
print(s3 is s4) # False (not interned)But if you build strings dynamically, Python may not reuse them:
s3 = "hello world!"
s4 = "".join(["hello", " world!"])
print(s3 == s4) # True
print(s3 is s4) # False- Both look the same, but they’re different objects in memory.
- Python optimizes small integers and certain strings. So
ismight accidentally return True. Don’t rely on this.
Lists Comparsion
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2) # True
print(list1 is list2) # False==says they’re equal because the contents match.issays they’re not identical because they live in different memory locations.
list3 = list1
print(list1 is list3) # TrueHere both names point to the same list. Changing list3 also changes list1.
Immutable objects (numbers, strings, tuples) can be cached and reused. Mutable objects (lists, dicts, sets) are usually new every time.
When to Use Each
Use ==
- When comparing values (almost always).
- Example: Checking if two user inputs are the same.
password1 = "secret123"
password2 = "".join(["secret", "123"])
print(password1 == password2) # True
print(password1 is password2) # FalseUse is
- When checking for object identity.
- Especially for
None.
value = None
if value is None: # Best practice
print("Value is missing")
Let’s Solve the Puzzle
What are the output?
a = 256
b = 256
c = 1000
d = 1000
print(a is b) # Line 1
print(c is d) # Line 2
print([1, 2, 3] == [1, 2, 3]) # Line 3
print([1, 2, 3] is [1, 2, 3]) # Line 4
Expand to reveal the output
Line 1 → True: 256 is cached, so a and b point to the same object.
Line 2 → False: 1000 is not cached, so c and d are different objects.
Line 3 → True: The two lists look the same, so == is True.
Line 4 → False: They’re different list objects, so is is False.
