Python for JS Devs · Fundamentals

Variables, types & truthiness

Where Python quietly disagrees with JS — and the bugs that come from assuming it doesn't.

Lesson 02Time ~12 min Win Predict Python's truthiness & equalityPrereq Lesson 01

Python's variables feel familiar — dynamic typing, reassignable — but three things differ enough to bite you: declaration, equality, and truthiness. This lesson is about the deltas, not the sameness.

1 · Declaration & naming

JavaScript
const maxRetries = 3;
let userName = "kd";
let result = null;
Python
MAX_RETRIES = 3   # UPPER = "constant" (convention only)
user_name = "kd"   # snake_case, not camelCase
result = None       # None ≈ null

2 · Equality: == vs is

Python's == compares values (roughly JS's ===, with no type coercion surprises). Python's is compares identity — same object in memory, like JS === on reference types.

JavaScript
a === b   // value/ref, no coercion
a == b    // coercing — avoid
x === null
Python
a == b            # value equality (use this)
a is b            # same object identity
x is None         # ALWAYS use `is` for None
The trap Use == for values, is only for None/True/False (singletons). Writing if x is 3: may work for small ints by luck and fail for others — never use is to compare values.

3 · Truthiness — the big one

This is where JS instincts betray you. In JS, [] and {} are truthy. In Python, empty collections are falsy.

JavaScript — truthy
if ([]) { ... }   // runs! [] is truthy
if ({}) { ... }   // runs! {} is truthy
// falsy: 0 "" null undefined NaN false
Python — falsy
if []:  ...        # skipped! empty list is falsy
if {}:  ...        # skipped! empty dict is falsy
# falsy: 0  0.0  ""  []  {}  ()  set()  None  False
Idiom you'll use constantly Because empty is falsy, the Pythonic "is this list non-empty?" is just if items: — not if len(items) > 0:. And "did I get a value?" is if value is not None: when 0/"" are legal values you must not treat as missing.

4 · Numbers & strings, briefly

7 / 2      # → 3.5   (true division, always float)
7 // 2     # → 3     (floor division)
7 % 2      # → 1     (modulo)
2 ** 10    # → 1024  (power, not Math.pow)

name = "kd"
f"hi {name.upper()}"   # f-string; strings are immutable
type(name)               # <class 'str'>
isinstance(name, str)   # True — prefer this over type() ==

🎯 Your win — predict, then check

Before running, write down what each prints. Then paste into uv run python:

print(bool([]), bool([0]), bool(""), bool("0"))
x = None
print(x is None, x == None)
print(7 / 2, 7 // 2)

Any surprise (especially bool("0")) is a JS instinct getting corrected — exactly the point.

Check yourself

Q1. What does if []: do in Python?
Empty collections are falsy in Python (the opposite of JS, where [] is truthy).
Q2. The correct way to test for None is:
None is a singleton — identity check with is is the idiom. null doesn't exist in Python.
Q3. What is the value of 7 / 2 in Python 3?
/ is true division and always returns a float. Use // for floor division.
Primary source Python docs — Truth Value Testing. The definitive list of what's falsy. Keep the syntax cheat sheet open too.
💬 Ask your teacher: confused about scope, or when is "accidentally" works on integers? That's a great question — bring it.