Q1Which of the following is the correct way to define a Python class?
Classes and Instances — Defining Your Own Type
Learn Python classes and instances from the ground up. Walk through class definitions, the role of self, and using __init__ to set attributes — all with diagrams.
As we touched on in the previous wrap-up, built-in types like int, str, list, and dict can't directly represent business concepts like "user," "product," or "order." The next step up is to define your own type with class — that's the entry point into object-oriented programming (OOP).
Why Object-Oriented Programming?
Everything you've written so far is procedural — combining functions to drive behavior. As programs grow, related data and the logic that operates on it tend to scatter, and changes and reuse get harder.
With object-oriented programming (OOP), you bundle the related data (attributes) and the operations on it (methods) into a single unit — an object. That lets you shape your code around real-world concepts.
function(data). OOP puts both inside an object so they live together.A Class Is a Blueprint, an Instance Is the Real Thing
Two terms anchor everything in OOP:
- Class — a blueprint that lists the attributes and methods you'll have
- Instance — the real thing built from that blueprint
For example, define a Product class to capture the concept of a product, and you can spin up as many individual product instances — apple, banana, orange — as you need. Together, classes and instances are called objects.
Defining a Minimal Class
Let's actually define a Product class for items in a store. The syntax is class ClassName:. By convention, Python class names use CapitalizedCamelCase (Product, UserAccount, etc.).
A variable written directly inside the class — like name = "apple" — is treated as a default value held by the class, and you can read it via the class name as Product.name.
class Product:
name = "apple"
price = 150
# Reach into the class directly
print(Product.name) # apple
print(Product.price) # 150
class — name / price — stick to the class itself and can be read directly via the class name as Product.name.Variables written directly under class are called class variables. They behave differently from instance variables (which each instance owns separately), but we'll come back to that distinction in a later article. For now, all you need is the minimal idea: "stick a value to the class itself, then read it as Product.name."
Use __init__ to Give Each Instance Its Own Values
The minimal class above just stuck a fixed value like name = "apple" to the class, so every instance you build would be "apple." In real code, you want multiple instances from one class — apple, banana, orange — each with its own values.
The tool for this is Python's special method __init__ — also known as the constructor or initializer. When you call Product("apple", 150) with arguments, Python automatically calls __init__, and inside it you write self.name = name to store values on the instance itself.
Double Underscores — A Python Convention
Names wrapped in double underscores like __init__ are called dunder methods. Python gives them special meaning and calls them automatically at certain moments — __init__ when an instance is created, __str__ when something is printed, and so on. We'll cover __init__ in more depth and meet __del__ in the next article.
Product("apple", 150) makes Python ① prepare an empty instance, ② pass it to __init__ as self, and ③ write the arguments onto that instance's attributes — leaving you with a finished object.class Product:
def __init__(self, name, price): # Called automatically when an instance is created
self.name = name
self.price = price
apple = Product("apple", 150)
banana = Product("banana", 80)
print(apple.name, apple.price) # apple 150
print(banana.name, banana.price) # banana 80
# apple and banana are different objects
print(apple is banana) # False
Product(...) creates a separate object. apple, banana, and orange all come from the same blueprint but are different objects, each with its own name / price.How Methods and self Work
Attributes alone just "hold data" — not much different from a plain dict. The real point of OOP is that you can also write operations on the instance alongside the data. Those operations are called methods.
def is a method. The first parameter self is required, and on each call Python fills it with the instance you called the method on. Inside the method, write self.name to access that instance's attributes.When you write apple.show(), Python is internally running Product.show(apple) — self ends up holding apple.
- apple and banana are separate instances
- When you call
apple.show()…
- self is filled with apple automatically
self.namereads apple.name- For
banana.show(),selfbecomesbananainstead
show method, calling from apple reads apple's name, calling from banana reads banana's.class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def show(self): # First parameter is always self
print(f"{self.name}: ${self.price}")
apple = Product("apple", 150)
banana = Product("banana", 80)
apple.show() # apple: $150 same as Product.show(apple) internally
banana.show() # banana: $80 same as Product.show(banana) internally
apple.show() puts apple into self, while calling banana.show() puts banana into self. The same show method runs with a different self every time, depending on the caller.self Is Just a Convention
Syntactically, the first parameter can be anything — def show(this): works too. But almost every Python codebase uses self, so stick with it. Anything else throws off readers.
In this article you got the basics of object-oriented programming. We'll cover variables and methods in more depth in later articles.
Knowledge Check
Answer each question one by one.
Q2What is automatically passed to a method's first parameter self when called?
Q3What does the following code print?class P: def __init__(self, x): self.x = xa = P(10)b = P(20)print(a.x + b.x)