Data StructuresLesson 2 of 3
Dictionaries (= Objects)
Python's dictionary fills the same role as a JS object used as a map: a collection of key-value pairs. But dicts are stricter. In a dict literal, string keys must be quoted ({"name": "Alice"}); an unquoted name would be treated as a variable. And you access values only with brackets, never dot notation: user.name looks for an attribute, not a key, and raises AttributeError.
Keys can be any hashable value, not just strings. Hashable roughly means immutable: strings, numbers, tuples of hashable items, and frozensets all work. Lists, dicts, and sets cannot be keys because they can change; trying it raises TypeError: unhashable type. Unlike JS objects, keys are not converted to strings, so d[1] and d["1"] are two different entries.
The safe access pattern is different too. Instead of user?.name ?? "default", Python uses user.get("name", "default"). It returns the default if the key is missing instead of raising KeyError. Clean and explicit.
Iteration is one area where Python dicts are genuinely nicer. Instead of Object.keys(), Object.values(), and Object.entries(), you call .keys(), .values(), and .items() on the dict itself, and 'for key in my_dict' just works. One rule: do not add or remove keys while iterating over a dict (changing values is fine). That raises RuntimeError: dictionary changed size during iteration. Loop over a copy of the keys instead: for k in list(my_dict):
Quick reference
| JavaScript | Python | Note |
|---|---|---|
| { name: "Alice" } | {"name": "Alice"} | String keys need quotes |
| obj.name | obj["name"] | No dot notation for dicts |
| obj.name ?? "default" | obj.get("name", "default") | .get() with default |
| Object.keys(obj) | obj.keys() / list(obj) | Method on the dict itself |
| Object.entries(obj) | obj.items() | entries -> items |
| { ...a, ...b } | {**a, **b} / a | b | a | b needs Python 3.9+ |
| delete obj.key | del d["key"] / d.pop("key") | pop() also returns the value |
| Object.fromEntries(arr.map(...)) | {k: v for k, v in pairs} | Dict comprehension |
Side by side
// JavaScript Objects
const user = {
name: "Alice",
age: 25,
skills: ["JS", "React"]
};
user.name;
user.country ?? "Unknown";
"name" in user;
Object.entries(user);
const updated = { ...user, age: 26 };
const squares = Object.fromEntries([0, 1, 2].map(x => [x, x ** 2]));# Python Dictionaries
user = {
"name": "Alice",
"age": 25,
"skills": ["JS", "React"],
}
user["name"] # brackets only!
user.get("country", "Unknown") # .get() + default
"name" in user # same!
user.items() # entries -> items
updated = {**user, "age": 26} # ** spread
updated = user | {"age": 26} # merge operator (3.9+)
# Dict comprehension (JS: Object.fromEntries + map)
squares = {x: x**2 for x in range(3)}Exercise
Real Python, running in your browserConvert this JavaScript to Python (use snake_case for every name, including the in_stock key):
// JavaScript
const product = {
name: "Laptop",
price: 999,
inStock: true
};
const discountedPrice = product.price * 0.9;
const hasWarranty = product.warranty ?? false;
for (const [key, value] of Object.entries(product)) {
console.log(`${key}: ${value}`);
}name: Laptop price: 999 in_stock: True
Ctrl + Enter runCtrl + Shift + Enter checkTab indentEsc then Tab to leave the editorCtrl + / comment