Back to List

Truthy/Falsy and is vs ==

This article clearly explains which values are evaluated as True/False in Python and the difference between 'is' and '=='.

Beginner
|
8min
|
Verified (2026-07)
truthyfalsyis==None comparisonPython comparison
Progress0/18 (0%)

Truthy/Falsy and is vs ==

After this topic

You will understand how values in Python are evaluated as True/False in conditional statements, and you will be able to correctly distinguish and use is and ==.


Truthy and Falsy

Python's if statement doesn't just accept True/False. Any value can be used as a condition:

python
if "hello":
print("executed!") # Executed!
if 0:
print("not executed") # Not executed

Python divides all values into Truthy (treated as true) and Falsy (treated as false).


Falsy Values β€” Just Memorize These

There are a fixed number of Falsy values. Everything else is Truthy:

python
# These are Falsy (evaluate to False)
False
None
0 # Integer 0
0.0 # Float 0
"" # Empty string
[] # Empty list
{} # Empty dictionary
set() # Empty set
python
# Let's verify
values = [False, None, 0, 0.0, "", [], {}, set()]
for v in values:
print(f"{str(v):10} β†’ {bool(v)}")
# False β†’ False
# None β†’ False
# 0 β†’ False
# 0.0 β†’ False
# β†’ False
# [] β†’ False
# {} β†’ False
# set() β†’ False

Key rule: "Empty or zero is Falsy". Just remember this.


Practical Pattern β€” Checking for Empty Values

Using Truthy/Falsy makes your code more concise:

python
# Checking if a list is empty
items = []
# No need to write this
if len(items) > 0:
print("exists")
# Just write this
if items:
print("exists")
python
# Checking if a string is empty
name = ""
if name:
print(f"Hello, {name}")
else:
print("Please enter your name")
python
# Checking for None and providing a default value
def greet(name=None):
name = name or "Guest"
return f"Hello, {name}"
print(greet()) # "Hello, Guest"
print(greet("철수")) # "Hello, 철수"

The or operator returns the right-hand side if the left-hand side is Falsy. This is often used as a default value pattern.


== β€” Are the Values Equal?

== compares if two values are equal:

python
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True β€” because the contents are the same

The two lists are separate objects, but since the values they contain are the same, == returns True.

python
print(1 == 1.0) # True β€” if the numerical values are the same
print("abc" == "abc") # True
print([1] == [1]) # True

is β€” Is it the Same Object?

is compares whether two variables point to the same object in memory:

python
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True β€” values are the same
print(a is b) # False β€” different objects
print(a is c) # True β€” pointing to the same object

a and b have the same contents but are different list objects. c = a points to the same list, so is is True.

python
# Can be verified with id()
print(id(a)) # 140234567890
print(id(b)) # 140234567920 (different address)
print(id(c)) # 140234567890 (same address as a)

Why You Should Use is for None Comparison

python
result = None
# βœ… Correct way
if result is None:
print("No result")
# ❌ Not recommended
if result == None:
print("No result")

None is a single object in all of Python. Comparing with is directly checks if "this is that one None object?".

== can behave unexpectedly if a class overrides the __eq__ method:

python
class Tricky:
def __eq__(self, other):
return True # Returns True when compared to anything
t = Tricky()
print(t == None) # True β€” dangerous!
print(t is None) # False β€” safe

PEP 8 (the official Python style guide) also explicitly states that is should be used for None comparisons.


Integer Caching Trap

python
a = 256
b = 256
print(a is b) # True β€” CPython caches -5 to 256 in advance
a = 257
b = 257
print(a is b) # False β€” creates a separate object outside the range

CPython pre-creates and reuses small integers (-5 to 256). Within this range, is is True, but outside it is False. This is why you shouldn't use is for value comparison. is should only be used for None, True, and False comparisons.

python
# Similar phenomenon with strings
a = "hello"
b = "hello"
print(a is b) # True β€” string interning in effect
a = "hello world!"
b = "hello world!"
print(a is b) # False β€” interning does not occur with spaces and special characters

Function Parameter Default Values and None

python
# ❌ Dangerous pattern
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a")) # ["a"]
print(add_item("b")) # ["a", "b"] β€” the result of the previous call remains!
# βœ… Safe pattern
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items

When mutable objects (lists, dictionaries) are used as default values, all calls share the same object. Using None as the default value and creating a new object inside the function is the standard Python pattern.


bool() and Utilizing Truthy/Falsy

python
# Concise empty value checking
data = {"name": "철수", "email": "", "phone": None}
# ❌ Long and repetitive
if data["name"] is not None and data["name"] != "":
print("name exists")
# βœ… Utilize Truthy/Falsy
if data["name"]:
print("name exists")
# Filter only valid values
values = [0, "", None, "hello", [], [1, 2], False, 42]
valid = list(filter(None, values))
print(valid) # ["hello", [1, 2], 42]

filter(None, iterable) removes all Falsy values. This is a pattern often used for data cleaning.


Summary

ComparisonMeaningWhen to Use
==Are the values equal?General value comparison
isIs it the same object?None, True, False comparison
!=Are the values different?General inequality check
is notIs it a different object?is not None
python
# Remember these patterns
if x is None: # Check for None
if x is not None: # Check if not None
if items: # Is it not empty (Truthy)
if not items: # Is it empty (Falsy)


any() and all() β€” Utilizing Truthy in Collections

python
scores = [85, 92, 0, 78, 95]
print(any(scores)) # True β€” at least one Truthy value (a value other than 0)
print(all(scores)) # False β€” 0 is Falsy
# Together with conditional expressions
print(any(s >= 90 for s in scores)) # True β€” is there a score greater than or equal to 90?
print(all(s >= 60 for s in scores)) # False β€” are all scores greater than or equal to 60?

any() and all() internally use Truthy/Falsy evaluation. They are useful for expressing conditions concisely.



Utilizing Short-circuit Evaluation

python
# or β€” returns the first Truthy value (or the last value if none)
name = user_input or "DefaultName"
# and β€” returns the first Falsy value (or the last value if none)
result = data and data[0] # returns [] if data is empty, otherwise returns the first element

or and and don't just return booleans; they return the value at the point where the Truthy/Falsy evaluation stops. This is often used for setting default values or in safe access patterns.


Not understanding the difference between == and is can lead to hard-to-find bugs. In particular, making it a habit to use is instead of == for None comparisons is fundamental to Python code quality.

πŸ’¬ Questions & Comments

0 comments

You can post without signing in. Guest comments cannot be edited or deleted by their author.

0/2000

Loading...