Lists And Dictionaries
These two carry almost all the data in agent code. A list is things in order. A dictionary is things looked up by name. Between them they describe conversation history, tool arguments, API responses, retrieved documents and graph state.
Learn these properly and a large amount of framework code becomes readable.
Lists
An ordered, changeable collection.
skills = ["Python", "SQL", "Cloud"]
print(skills[0])
print(skills[-1])
print(len(skills))
skills.append("AI Agents")
print(skills)Python
Cloud
3
['Python', 'SQL', 'Cloud', 'AI Agents']Counting from zero, and counting backwards
This is worth doing slowly, because it catches everyone once.
students = ["Amit", "Sara", "John", "Anil"]
print(students[0])
print(students[2])
print(students[-1])
print(students[10])students[0]is the first item, not the second. Counting starts at zero.students[-1]is the last. In Java or C# that would throw; Python treats it as counting from the end, and it is genuinely useful.students[10]raisesIndexError, because there is no eleventh student. That error is Python working correctly, not your notebook being broken.
The methods you need
items = ["a", "b", "c"]
items.append("d")
items.insert(0, "z")
items.remove("b")
last = items.pop()
items.sort()
items.reverse()
print("a" in items)
print(items.index("c"))| Method | Does |
|---|---|
.append(x) | add to the end |
.insert(i, x) | add at a position |
.remove(x) | remove the first matching value |
.pop() | remove and return the last item |
.sort() | sort in place |
in | is it present |
.index(x) | where is it |
Note that .sort() changes the list and returns None. sorted(items) returns a new sorted list and leaves the original alone. Writing items = items.sort() sets items to None, which is a memorable afternoon.
Slicing
items = ["a", "b", "c", "d", "e"]
print(items[:2])
print(items[2:])
print(items[-2:])Same rules as strings. items[:2] is up to but not including position 2.
Slicing a list gives a new list, which is the shortest way to copy one:
copy = items[:]Dictionaries
Values looked up by name rather than position.
member = {
"name": "Priya",
"role": "Data Architect",
"years": 14,
}
print(member["role"])
member["city"] = "Pune"
print(member)Curly braces, key: value pairs, commas between. Keys are usually strings.
Missing keys
print(member["salary"])KeyError: 'salary'Square brackets demand the key exists. When it might not, use .get():
print(member.get("salary"))
print(member.get("salary", "not disclosed")).get() returns None when the key is absent, or the default you supply.
For anything that came from a model or an external API, assume keys may be missing. This single habit removes most crashes in early agent code.
Walking a dictionary
for key in member:
print(key)
for key, value in member.items():
print(key, "=", value)
print(list(member.keys()))
print(list(member.values()))Looping a dictionary directly gives you the keys. When you want both, use .items(). Forgetting that is a common early error.
Useful bits
print("role" in member)
member.update({"years": 15, "tier": "diamond"})
member.pop("city", None)in checks keys, not values. .pop(key, None) removes safely whether or not the key was there.
Nesting, which is where real data lives
Real responses are dictionaries inside dictionaries, and lists of dictionaries.
response = {
"status": "success",
"ticket": {
"id": 4471,
"severity": "P2",
"tags": ["network", "urgent"],
},
}
print(response["ticket"]["severity"])
print(response["ticket"]["tags"][0])Work left to right, one step at a time. response["ticket"] is a dictionary, so you can index it again. ["tags"] is a list, so you index it by position.
When you are unsure of the shape, print it laid out:
import json
print(json.dumps(response, indent=2))That one line will save you more debugging time than anything else on this page.
The shape you will see most often
A list of dictionaries. It is the standard format for conversation history and for rows of anything.
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Why is the server down?"},
{"role": "assistant", "content": "Let me check the logs."},
]
for m in messages:
print(f"{m['role']}: {m['content']}")
messages.append({"role": "user", "content": "Thanks"})
print(len(messages))Note the single quotes inside the f-string braces — the outer string already uses double quotes, so the inner ones must differ.
This exact structure is what every chat API accepts, what LangGraph carries in state["messages"], and what you will read and write hundreds of times.
Tuples and sets, briefly
point = (12, 45)
unique_owners = {"network", "database", "network"}
print(unique_owners)- a tuple is a list that cannot be changed. Used for fixed pairs and for returning several values
- a set has no duplicates and no order. Used for de-duplicating
Neither is as common as lists and dictionaries in agent code, but you will see them.
Coming from Java or C#
| Concept | Java | C# | Python |
|---|---|---|---|
| Growable list | ArrayList<T> | List<T> | list |
| Map | HashMap<K,V> | Dictionary<K,V> | dict |
| Set | HashSet<T> | HashSet<T> | set |
| Fixed pair | no clean form | Tuple | tuple |
| Size | .size(), .Count | len(x) | |
| Add | .add(x) | .Add(x) | .append(x) |
| Get by key | .get(k) | [k] | [k] or .get(k) |
| Missing key | returns null | throws | [k] throws, .get(k) returns None |
| Contains | .contains(x) | .Contains(x) | x in y |
Three differences worth holding on to:
- a Python list holds anything, including a mixture. There is no
List<String>at runtime, onlylist len()is a function, not a methodmap.get(k)in Java returns null for a missing key; Python'sd[k]throws..get()is the forgiving one
Common mistakes
items = items.sort(), which sets it toNone. Usesorted()or just call.sort().d["key"]on data you did not create. Use.get().- Looping a dictionary and expecting pairs. You get keys; use
.items(). - Expecting
b = ato copy. It does not. Usea.copy()ora[:]. - Modifying a list while looping over it, which skips items. Build a new list instead.
- Assuming order in a set. There is none.
Practise this
- Build a list of four names. Print the first, the last, and the length. Then trigger an
IndexError. - Build a dictionary describing yourself. Read one key that exists and one that does not, safely.
- Build a list of three message dictionaries and print each as
role: content. - Read a value three levels deep out of a nested response, then print the whole thing with
indent=2.