Appendix A · Refresher

From Java & JavaScript to Python

You already know how to program. This appendix maps what you know from Java and JavaScript onto Python, and flags the habits that cause bugs. Read it first, or come back whenever something feels "almost but not quite" familiar.

You will refresh

  • Syntax, typing and the "everything is a reference" object model.
  • Equality, None, truthiness and numbers: the four biggest sources of surprises.
  • Collections, loops, functions and classes, side by side.
  • Interfaces vs duck typing, and exceptions without throws.
  • Classic design patterns, done the Pythonic way.

1. Syntax at a glance

Python uses indentation instead of braces, newlines instead of semicolons, and words instead of symbols for logic.

Java / JSPython
{ … } blocks: plus 4-space indentation
// comment, /* */# comment; docstrings """…"""
&& || !and or not
true false null / undefinedTrue False None
else ifelif
x++x += 1
cond ? a : ba if cond else b
camelCase methodssnake_case (PEP 8)

In Python: Chapter 1 (indentation) and Chapter 3 (if/elif, the conditional expression).

Quick check: how do you write x = flag ? 1 : 0?

x = 1 if flag else 0

2. Dynamic typing (with optional hints)

In Java, a variable has a type. In Python, only objects have types; a variable is just a name that can point to anything. Type hints exist, but Python doesn't check them at run time. Tools like mypy do. Unlike JS, Python is strongly typed: it never converts types silently.

In Python: Chapter 5 (annotations), Chapter 1 (the TypeError).

Quick check: what does int("7") + 1 give?

8. You convert explicitly with int(), float() or str().

3. Everything is an object; variables are references

Python has no primitives: 3, True and functions are all objects. Every variable holds a reference, and assignment never copies. It is exactly how Java object references and JS object variables behave, just applied to everything. Mutability is what decides whether sharing matters.

Immutable (safe to share)Mutable (shared changes are visible)
int float bool str tuple frozenset frozendict bytes Nonelist dict set bytearray, most user objects

In Python: Chapter 2 (aliasing), Chapter 5 (passing by object reference), Chapter 11 (names and objects).

Quick check: after t = (1, [2]); t[1].append(3), what is t?

(1, [2, 3]). The tuple is immutable, but the list inside it is not.

4. Equality and identity: ==, is, None

Python's == compares values, so it is Java's .equals(), and you can use it on strings. is compares identity (the same object), which is Java's == on references. Use is only for singletons like None. There is one "nothing" value, None; there is no undefined.

⚠️ x is 5 or s is "abc" might seem to work, because of interning, but it is unreliable, and Python warns: SyntaxWarning: "is" with 'int' literal.

In Python: Chapter 7 (more on conditions), Chapter 11 (__eq__).

Quick check: which do you write, if x == None or if x is None?

if x is None. It is faster and can't be fooled by a custom __eq__.

5. Truthiness, Python vs JavaScript

Both languages have "falsy" values, but the lists differ. In Python, empty containers are false, which JS doesn't do for [] and {}.

ValueJSPython
[] / {}truthyfalse
"", 0falsyfalse
"0", "false"truthytrue
NaNfalsyfloat("nan") is true
null / Nonefalsyfalse

In Python: Chapter 3 (truthiness), Chapter 7 (and/or return operands).

Quick check: what is [] or "default"?

'default'. The empty list is false, so or returns its second operand.

6. Numbers

int has unlimited size (no overflow), / always returns a float, and // floors toward minus infinity. Floats are IEEE-754 doubles, like Java's double and JS's number.

In Python: Chapter 2 (numbers and floats), Chapter 14 (Decimal).

Quick check: Java's -7 / 2 is -3. How do you get -3 in Python?

int(-7 / 2), which truncates toward zero. -7 // 2 gives -4.

7. Strings

Strings are immutable Unicode, as in Java. There is no char type (a character is a 1-length str), and no StringBuilder: collect parts in a list and "".join() them. Template literals become f-strings.

Java / JSPython
`Hi ${name}` / String.formatf"Hi {name}"
s.length() / s.lengthlen(s)
s.substring(1, 3) / s.slice(1, 3)s[1:3]
s.contains("x") / s.includes("x")"x" in s
String.join(",", list) / arr.join(",")",".join(items)
s.trim()s.strip()

In Python: Chapter 2 (text), Chapter 9 (f-strings).

Quick check: how do you get the last 3 characters of s?

s[-3:]

8. Collections

JavaJavaScriptPython
ArrayListArraylist [1, 2]
HashMap / LinkedHashMapObject / Mapdict {"k": 1} (keeps insertion order)
HashSetSetset {1, 2}
record / small arrayssmall arraystuple (1, "a"), namedtuple, @dataclass
ArrayDeque—collections.deque
PriorityQueue—heapq
stream().filter().map().filter().map()comprehensions [f(x) for x in xs if p(x)]

In Python: Chapters 6 and 7.

Quick check: what happens with prices["coffee"]?

KeyError: a missing key raises; it doesn't return null. Use .get() for a default.

9. Loops

There is no C-style for (;;). for always iterates over items, and you ask for indexes with enumerate(). while is the same as in Java. Loops can have an else that runs when no break happened.

In Python: Chapter 3, and Chapter 7 (looping techniques).

Quick check: how do you loop over two lists in parallel?

for a, b in zip(xs, ys): (add strict=True to catch lists of different lengths).

10. Functions

Functions are first-class objects, like in JS. There is no overloading: use default values, keyword arguments, *args and **kwargs instead. Lambdas can only contain a single expression. Closures capture variables, not values.

In Python: Chapter 5.

Quick check: why is def f(items=[]) dangerous?

The default list is created once and shared between calls. Use None and create the list inside the function.

11. Classes

this becomes an explicit self parameter. The constructor is __init__, and there is no new. There are no access modifiers: _name means "internal" by convention. static becomes a class variable, @classmethod or @staticmethod. Getters and setters become plain attributes, or a @property if you need logic later.

In Python: Chapter 11.

Quick check: what is the Python version of Java's record Point(int x, int y)?

@dataclass(frozen=True) class Point: x: int; y: int

12. Interfaces → duck typing, ABCs and Protocols

Python cares whether an object has the right methods, not what it declares itself to be. That is duck typing. When you want a formal contract, use an abstract base class (abc.ABC), which errors if you instantiate an incomplete subclass, or a typing.Protocol, which is structural and checked only by type checkers, like TypeScript interfaces.

In Python: Chapter 11 (polymorphism without interfaces), Chapter 12 (the iterator protocol is duck typing).

Quick check: what makes an object usable in a for loop?

An __iter__ method (or __getitem__). No interface declaration is needed: that is duck typing.

13. Exceptions

try/catch/finally becomes try/except/finally, plus an else clause. throw becomes raise. There are no checked exceptions and no throws clause. The Python style is EAFP: try the operation and handle the failure, instead of checking every condition first.

In Python: Chapter 10.

Quick check: what is the Python version of Java's try-with-resources?

The with statement: with open(path) as f: …

14. Design patterns, the Pythonic way

Because functions are objects and modules are singletons, many Gang-of-Four patterns shrink to a few lines in Python, or disappear entirely.

PatternTypical JavaPythonic
Singletonprivate constructor + getInstance()a module: it is imported once (Chapter 8)
Strategy / Commandan interface + classespass a function (key=, a dispatch dict)
IteratorIterator<T> classa generator with yield (Chapter 12)
Factory methoda static factorya @classmethod like from_dict (Chapter 11)
Buildera fluent builder classkeyword arguments with defaults, or a dataclass
Decoratorwrapper classes@decorator functions (@property, @dataclass)
Template methodan abstract classan ABC, or simply pass the varying step as a function
Observerlistener interfacesa list of callables

In Python: Chapter 5 (functions as values), Chapter 8 (modules), Chapter 16 (the dispatch table in cli.py).

Quick check: what is the simplest Python Singleton?

A module-level object, e.g. config = Config() in settings.py. Every import settings shares it.

Recap: prerequisite feature → where you see it in Python

You know (Java/JS)Python equivalentWhere in this book
braces, semicolonsindentation, newlinesCh. 1, 3
static typesdynamic types + optional hintsCh. 5
object referencesevery name is a referenceCh. 2, 11
.equals() / =====; is for identityCh. 7
null / undefinedNoneCh. 5
for-each, iteratorsfor … in, generatorsCh. 3, 12
switchmatchCh. 4
overloading, varargsdefaults, *args, **kwargsCh. 5
ArrayList, HashMap, HashSetlist, dict, setCh. 6, 7
packages, importsmodules, packages, importCh. 8
try/catch, throwstry/except, no checked exceptionsCh. 10
classes, interfacesclasses, duck typing, ABCsCh. 11
JUnit, Maven/npmunittest/pytest, venv + pipCh. 13, 15

Exercises

Exercise 1 🟢 easy refactor it

Translate to Python: for (int i = 0; i < names.length; i++) { System.out.println(i + ": " + names[i]); }

Show solution

enumerate replaces the index counter. The f-string replaces the string concatenation.

Exercise 2 🟢 easy predict the output

What does this print? print([] == [], [] is [], bool([]), bool("False"))

Show solution

True False False True. The two lists have equal values but are different objects. An empty list is false, and any non-empty string is true.

Exercise 3 🟢 easy fix the bug

A JS developer wrote this. Fix all four problems.

Show solution

function becomes def, braces become a colon and indentation, let and const disappear, and of becomes in. Avoid naming a variable sum, because it hides the built-in sum(), which does this whole job anyway.

Exercise 4 🟢 easy explain why

Why does Python not need getX() and setX() methods?

Show solution

A public attribute can later become a @property without changing any caller's code (obj.x still works). So you start simple and add logic only when you need it.

Exercise 5 🟡 medium refactor it

Translate this Java stream: list.stream().filter(s -> s.length() > 3).map(String::toUpperCase).collect(Collectors.toList())

Show solution

A comprehension does the filter and the map in one readable expression.

Exercise 6 🟡 medium build it

Implement the Strategy pattern for shipping costs without any classes: standard (a flat €5), express (€5 plus 10% of the order) and free (orders over €100 ship free, otherwise standard). Choose a strategy by name.

Show solution

Each strategy is just a function stored in a dict. Adding a new strategy means adding one function and one dict entry.

Exercise 7 🟡 medium predict the output

What does this print?

Show solution

[1, 2, 3, 4] Ana. The list was mutated through the shared reference. name += "!" created a new string and only rebound the local name, because strings are immutable.

Exercise 8 🟡 medium build it

Write an Observer: a class EventBus with subscribe(fn) and publish(event), using plain functions as listeners.

Show solution

No listener interface is needed: anything callable works. Returning fn from subscribe makes it usable as a decorator, as the @bus.subscribe line shows.

Exercise 9 🔴 hard explain why

In Java, Integer a = 1000, b = 1000; a == b is false. In Python, 1000 == 1000 is always True, but a is b may be either. Explain both languages' behaviour.

Show solution

Java's == on boxed Integers compares references, and only small values (−128 to 127) are cached. Python's == always compares values. Python's is compares identity, and whether two equal ints are the same object is an implementation detail (CPython caches small ints and reuses constants). So never use is for numbers or strings.

Exercise 10 🔴 hard mini-project

Port this Java-style design to idiomatic Python: an interface Shape with area(), classes Circle and Rect, a ShapeFactory.create(String type, double... args), and a loop that prints the shapes sorted by area. Use an ABC, dataclasses, a dict-based factory, and sorted(key=…).

Show solution

Classes are first-class values, so the "factory" is a dict lookup. Dataclasses remove the constructor boilerplate, and key= replaces a Comparator.

Official docs