Variables, types, data structures
four containers that almost everything is built from
What it is
Almost all data in a program sits in one of four structures: a dictionary, a list, a tuple or a set. Knowing how they differ makes reading code much faster — the shape of the brackets alone tells you what is going on.
We will also cover type annotations (text: str) separately: they appear
constantly in AI-written code and read more easily than they look.
What it looks like in code
user = {"id": 7, "name": "Ola", "cities": ["Tønsberg", "Oslo"]}
print(user["name"])
print(user.get("email"))
print(user.get("email", "not set"))
cities = user["cities"]
cities.append("Bergen")
print(user["cities"]) # the original changed too
point = (59.27, 10.41)
lat, lon = point
print(lat, lon)
seen = {"Oslo", "Bergen", "Oslo"}
print(sorted(seen), len(seen))Output:
Ola
None
not set
['Tønsberg', 'Oslo', 'Bergen']
59.27 10.41
['Bergen', 'Oslo'] 2The four structures
| Kind | Brackets | What for | Sign in code |
|---|---|---|---|
| Dictionary | {"key": value} | data with named fields | access by x["name"] |
| List | [1, 2, 3] | an ordered collection | access by index x[0], .append() |
| Tuple | (1, 2) | a set of values nobody changes | unpacking a, b = x |
| Set | {1, 2, 3} | unique values | a check like if x in seen |
Curly braces mean both a dictionary and a set — easy to tell apart: if there are colons inside, it's a dictionary.
Two lines worth noticing
print(user.get("email")) # None
print(user.get("email", "not set"))user["email"] raises KeyError when the key is missing. user.get("email")
quietly returns None. The difference matters and comes up constantly in
AI-written code: .get() is a favourite way to "fix" an error by hiding it
(article 2.14).
cities = user["cities"]
cities.append("Bergen")
print(user["cities"]) # ['Tønsberg', 'Oslo', 'Bergen']cities is not a copy, it is the same thing. Lists and dictionaries are
passed by reference: change one and both change. This is the source of a
whole class of bugs that look like magic.
Type annotations
def add_reminder(user_id: int, text: str) -> int:Read left to right: user_id is an integer, text is a string, the function
returns an integer. This is a hint for the reader, not a check: Python does
not enforce annotations, and nothing stops you passing a string where a number
was promised.
The ones you will meet most often:
| Written | Means |
|---|---|
str, int, float, bool | string, integer, float, true/false |
list[str] | a list of strings |
dict[str, int] | a dictionary: string keys, integer values |
str | None | a string or nothing |
-> None | the function returns nothing |
str | None is especially useful when reading: it tells you outright that the
result has to be checked.
What to tell the AI
Which data structures are used in this file and what is in
each? Briefly, one line per variable.A useful question when data comes from outside:
Show me an example of the data that will reach this function.
One happy case and one with missing fields.When you need to know whether something changes unexpectedly:
Does this function modify the list it was given, or build
a new one?What to look for
.get() where an error is wanted. If a field is required, its absence is
an error, not a reason to substitute None. A silent None surfaces later
and further from the cause.
Modifying what was passed in. A function received a list and appended to it — the caller's list changed too. If that wasn't intended, hard bugs follow.
A dictionary instead of a proper structure.
data["result"]["items"][0]["price"] is a sign nobody parsed the data. Every
link in that chain can fail, and the traceback will only show the last one.
Annotations that don't match the code. -> str while the function
sometimes returns None. Annotations check nothing, so they can drift away
from the code unnoticed.
Cheat sheet
Four structures: dictionary · list · tuple · set.
Curly braces with colons — a dictionary; without — a set.
x["k"]fails on a missing key,x.get("k")returnsNone.Lists and dictionaries are passed by reference: change one, both change.
str | Nonein an annotation — the result must be checked.Annotations check nothing; they are for the reader.