Classes and objects
Why this matters
Most libraries you'll use in AI work hand you objects. The Anthropic SDK gives you a client object with a messages.create method. The reply it returns is an object with .content and .usage. A NumPy array is an object with .shape and .mean(). Once you know how classes work, those dots stop being magic. You can read them, and bundle your own data and logic the same way.
- Define a class with __init__ and create objects from it
- Store data on an object as attributes and act on it with methods
- Explain what self refers to
- Read a dataclass, and judge when writing a class is worth it
Data and the functions that use it
You've stored a campaign as a dictionary and written functions like roas(revenue, spend) that work on that data. The data and the functions belong together, but nothing in the code says so.
A class bundles them. Think of a cookie cutter: one shape, used to make many cookies, each with its own icing. The class is the cutter. It describes what data each thing holds (its attributes) and what it can do (its methods). An object, also called an instance, is one cookie: one particular thing made from the class.
class Campaign: def __init__(self, name, spend, revenue): self.name = name self.spend = spend self.revenue = revenue def roas(self): return self.revenue / self.spend spring = Campaign("Spring Sale", 3120.5, 15840) video = Campaign("Brand Video", 6400, 2870) print(spring.name, round(spring.roas(), 2)) print(video.name, round(video.roas(), 2))
The pieces:
class Campaign:starts the blueprint. Class names use CapWords (EmailCampaign), unlike the snake_case of variables and functions.__init__(two underscores on each side) runs automatically when you create an object. Its job is to set the starting attributes.self.name = namestores the value as an attribute on this particular object.roasis a method: a function defined inside the class. You call it with a dot,spring.roas().Campaign("Spring Sale", 3120.5, 15840)creates a new object and runs__init__with those arguments.
spring and video share the same code but hold different data. Each object keeps its own attributes.
What self is
Every method's first parameter is self: the object the method was called on. When you write spring.roas(), Python runs Campaign.roas(spring) behind the scenes. So inside the method, self is spring, and self.revenue is spring's revenue.
class Campaign: def __init__(self, name, spend, revenue): self.name = name self.spend = spend self.revenue = revenue def roas(self): return self.revenue / self.spend spring = Campaign("Spring Sale", 3120.5, 15840) print(spring.roas()) print(Campaign.roas(spring))
Both lines do the same thing. You always write self as the first parameter in the definition. You never pass it yourself: Python fills it in from whatever is before the dot.