AlgoMaster Logo

Exercise: Object-Oriented Python and Dataclasses

3 min readUpdated June 22, 2026
Listen to this chapter
Unlock Audio

Exercise 1: Build a Conversation with Dataclasses

Model a chat conversation with a Message dataclass, then serialize a list of messages into the exact format an LLM API expects: a list of dictionaries, each with a role and a content key.

Every chat request you send is a list of these message dictionaries. Using a dataclass to represent a message gives you type checking, sensible defaults, and a single place to define the structure, instead of passing around loose dictionaries that are easy to typo.

Requirements

  • Define a Message dataclass with role and content fields.
  • Build a short conversation: a system message, a user message, and an assistant message.
  • Write a function that converts a list of Message objects into a list of {"role": ..., "content": ...} dictionaries.
  • Print the serialized list.
main.py
Loading...

Expected Output

The serialized output is the message list you would pass straight to client.chat.completions.create(messages=...).

Solution

main.py
Loading...

asdict from the dataclasses module turns a dataclass instance into a dictionary whose keys are the field names, in the order they were declared. That gives you the {"role": ..., "content": ...} shape for free, so the serialization function is a single comprehension. Because the structure lives in the Message definition, changing the message shape later means editing one class rather than every place that builds a dictionary by hand.

Exercise 2: A Self-Trimming Conversation

Wrap the message list in a Conversation class that keeps itself within a maximum size. Each time you add a message, the class drops the oldest messages so the conversation never grows past max_messages.

This bundles state and behavior the way real chat clients do: the conversation owns its messages and its trimming rule, so callers just add and never worry about the window. It is the object-oriented version of the memory management you will see again with agents.

Requirements

  • Give Conversation a max_messages limit and a list of messages.
  • Implement add(role, content) to append a Message and then drop the oldest until the list fits max_messages.
  • Add five messages to a conversation with max_messages=3 and print what remains.
main.py
Loading...

Expected Output

Only the three most recent messages survive.

Solution

main.py
Loading...

Putting the trimming logic inside add means the invariant (never more than max_messages) holds automatically after every call, so no caller can forget to enforce it. The dataclass gives you the message structure and a clean constructor for free. This is the same pin-and-window idea used for agent memory, expressed as a small object that manages its own state.