Python for Java Developers: Syntax, Types, and the Mental Model Shift
Part 1 of the Python for Java Developers track. Last updated: October 2026.
You already know how to think like a programmer — Python just asks you to think a little differently. This post is the bridge: dynamic typing, indentation-based blocks, truthiness, None vs null, and the collection types you'll reach for every day. Java snippets are shown alongside so you can map what you know onto what's new.
Variables and types: names, not boxes
In Java, a variable is a typed box. In Python, a name is a label stuck on an object — the object has the type, the name doesn't. Reassigning a name to a different type is normal, not a compiler error:
// Java: the box has a type int count = 5; count = "five"; // compile error
# Python: the name is just a label count = 5 count = "five" # perfectly fine — the label moved to a str object print(type(count)) # <class 'str'>
Indentation is syntax
Python has no braces. Indentation defines blocks — four spaces is the convention (PEP 8). Your editor handles it; your eyes will thank you:
// Java: braces define the block
for (int i = 0; i < 3; i++) {
if (i % 2 == 0) {
System.out.println(i + " is even");
}
}
# Python: indentation defines the block
for i in range(3):
if i % 2 == 0:
print(f"{i} is even")
# 0 is even
# 2 is even
Truthiness: every object is a boolean
Java's if demands a boolean. Python's if accepts anything and applies truthiness: empty collections, zero, None, and empty strings are falsy; everything else is truthy. This replaces most null/empty checks with one line:
// Java: explicit emptiness checks
if (orders != null && !orders.isEmpty()) {
process(orders);
}
# Python: truthiness does the whole check
if orders: # False for None, [], {}, "", 0
process(orders)
print(bool([]), bool([1]), bool(None), bool("x"))
# False True False True
None is not null (quite)
Python's None is Java's null — a singleton meaning "no value". Two differences that matter: comparing with is (identity) instead of ==, and the classic mutable-default-argument trap, which None elegantly avoids:
result = None
if result is None: # use `is`, not `==`, for None
print("no result yet")
# no result yet
def add_item(item, basket=None): # None as sentinel — the Python idiom
if basket is None:
basket = [] # fresh list every call; no shared-mutable bug
basket.append(item)
return basket
print(add_item("a"), add_item("b"))
# ['a'] ['b']
Collections: list, dict, set, tuple
Your Java collections map almost one-to-one — with shorter names and literal syntax. dict is HashMap, set is HashSet, list is ArrayList, and tuple is an immutable list (great for returning multiple values):
names = ["ada", "grace"] # list ~= ArrayList
names.append("hopper")
lookup = {"ada": 1, "grace": 2} # dict ~= HashMap
unique = {"ada", "grace"} # set ~= HashSet
point = (10, 20) # tuple — immutable
first, second = names # unpacking — no get(0), get(1)
print(first, lookup["ada"], len(unique), point[0])
# ada 1 2 10
Comprehensions: loops that read like set-builder notation
Java streams are powerful but verbose. Comprehensions build lists, dicts, and sets in one readable expression — the single Python feature Java developers end up using most:
// Java: stream pipeline for a filtered, mapped list
List<String> loud = names.stream()
.filter(n -> n.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
# Python: a comprehension does the same in one line
loud = [n.upper() for n in names if len(n) > 3]
squares = {n: len(n) ** 2 for n in names} # dict comprehension
print(loud, squares)
# ['GRACE', 'HOPPER'] {'ada': 9, 'grace': 25, 'hopper': 36}
Key takeaways
- Names are labels on typed objects, not typed boxes — reassignment across types is normal.
- Indentation defines blocks; four spaces per PEP 8, no braces.
- Truthiness replaces null/empty checks: if orders: covers None, [], {}, "", and 0.
- Compare None with is; use None as the sentinel for optional mutable arguments.
- list/dict/set/tuple map to ArrayList/HashMap/HashSet/immutable-list — with literal syntax.
- Comprehensions are your streams replacement: [f(x) for x in xs if cond].
Next in this series: Java to Python: Classes, Exceptions, and the Standard Library.
Comments
Post a Comment