What professional code looks like when it doesn't live in one long file.
Fundamentals 13 min Beginner April 26, 2026
You have been using objects since your first line of Python. "Hello" is an object of class str, [1, 2, 3] is an object of class list, and every time you called .append() or .upper(), you were calling a method on an object. Object-oriented programming (OOP) is the system behind this: it bundles data and the operations that belong to it into reusable units.
When you open PyTorch, Hugging Face, or scikit-learn, everything you interact with — models, tokenizers, optimizers — is an object created from a class. Understanding OOP turns cryptic library documentation into something you can actually read.
The Class: A Blueprint for Objects
Class
AnalogyDefinition
A class is like a car manufacturer's blueprint for a specific model. The blueprint specifies that every car will have a color, an engine power rating, and a VIN — and that every car can accelerate and brake. But the blueprint itself does not drive — it only describes what the cars built from it will be able to do.
Analogy:
A class is like a car manufacturer's blueprint for a specific model. The blueprint specifies that every car will have a color, an engine power rating, and a VIN — and that every car can accelerate and brake. But the blueprint itself does not drive — it only describes what the cars built from it will be able to do.
Definition:
A class is a template defined with the class keyword. It specifies the structure (attributes) and behavior (methods) that every instance will have. __init__ is called automatically when a new object is created and sets up its initial state. self refers to the specific object.
The blueprint analogy breaks at three points: (1) Software classes can inherit from other classes — physical blueprints don't compose this way. (2) Python objects can gain new attributes at runtime — like a car suddenly growing wings. (3) Creating a new software object costs almost nothing, while building a new car costs materials and labor.
self.name = "Bello" and self.breed = "Labrador" are set
5
Finished object is returned and stored in my_dog
Example: A Dog Class
class Dog:
def __init__(self, name, breed):
self.name = name # Attribute
self.breed = breed # Attribute
def bark(self): # Method
print(f"Woof! I am {self.name}")
my_dog = Dog("Bello", "Labrador")
my_dog.bark() # Output: Woof! I am Bello
class defines the blueprint. __init__ sets up each new object. self always refers to the specific object being created or used. Attributes (self.name) store data on the object. Methods (bark) define behavior.
Common Mistake: Forgetting self
If you forget self in a method signature, you get a confusing error message. Python automatically passes the object as the first argument — without self, the method expects zero arguments but receives one.
class Dog:
def bark(): # self is missing!
print("Woof!")
my_dog = Dog()
my_dog.bark()
# TypeError: bark() takes 0 positional
# arguments but 1 was given
The Object: A Living Instance
Object
AnalogyDefinition
If the class is "VW Golf" (the model), the object is the specific red Golf parked in front of your house with 23,456 km on the odometer and a scratch on the left door. Five Golfs from the same factory are five independent objects sharing the same blueprint but having different mileage, damage, and owners.
Analogy:
If the class is "VW Golf" (the model), the object is the specific red Golf parked in front of your house with 23,456 km on the odometer and a scratch on the left door. Five Golfs from the same factory are five independent objects sharing the same blueprint but having different mileage, damage, and owners.
Definition:
An object is a concrete instance of a class — a real entity in memory with its own identity, type, and state. Instantiation is the act of creating an object by calling the class name like a function. There can be any number of objects from the same class, each with their own attribute values.
The car analogy breaks because: (1) Software objects are destroyed when the program ends — real cars persist physically. (2) Objects can query their own class (type(dog1)), while cars don't "know" their blueprint. (3) Objects can be trivially copied — creating a perfect car clone is impossible.
Class (Blueprint)
Defines structure and behavior. Does not act itself. Dog describes what dogs can do — but Dog does not bark.
Object (Instance)
Has its own data and executes methods. my_dog has the name "Bello" and can bark().
Instance Independence
dog1 = Dog("Bello", "Labrador")
dog2 = Dog("Rex", "Shepherd")
print(dog1.name) # Bello
print(dog2.name) # Rex
dog1.name = "Wuffi"
print(dog1.name) # Wuffi
print(dog2.name) # Rex (unchanged!)
Each object has its own attribute values. Changing dog1.name has no effect on dog2.name — they are independent copies of the blueprint. This is the core principle: objects share structure, but not data.
Why OOP Is in Every AI Library
The three major AI libraries — PyTorch, Hugging Face Transformers, and scikit-learn — are entirely built on classes and objects. You don't need to write your own classes to use AI — but you need to understand that you are using objects and calling methods on them.
P
PyTorch
Every model inherits from nn.Module. The class defines layers in __init__ and data flow in forward(). model = nn.Linear(10, 5) creates an object with .weight and .bias attributes.
H
Hugging Face
GPT2Model.from_pretrained("gpt2") is a class method that creates an object and loads pretrained weights. The object can then be called like a function: model(**inputs).
S
scikit-learn
clf = DecisionTreeClassifier() creates an object. clf.fit(X, y) trains it — the learned state is stored in the object. clf.predict(X_test) uses that state for predictions.
The pattern is the same everywhere: import makes the class available, the constructor (or a factory method) creates an object, and method calls use or modify the object's state. When you read .fit(), .predict(), or .forward(), you are reading method calls on objects.
Not Everything Needs a Class
Understanding OOP does not mean wrapping everything in classes. Simple scripts work perfectly with functions. Use classes when you need reusable, stateful units — not as an end in themselves.
Deep Dive: Class vs. Instance Attributes
Attributes defined directly in the class (outside of __init__) are shared by all instances. Attributes set in __init__ via self belong to the individual object.
class Dog:
species = "Canis lupus familiaris" # Class attribute
def __init__(self, name):
self.name = name # Instance attribute
dog1 = Dog("Bello")
dog2 = Dog("Rex")
print(dog1.species) # Canis lupus familiaris
print(dog2.species) # Canis lupus familiaris (shared!)
print(dog1.name) # Bello (individual)
Watch out for mutable class attributes! A list as a class attribute is shared by all instances — changes by one object affect all others. Rule of thumb: always define mutable data (lists, dictionaries) in __init__ as instance attributes.
Deep Dive: Inheritance — Standing on the Shoulders of Giants
class MyModel(nn.Module) means: MyModel IS an nn.Module with extra features. The child inherits all methods and attributes of the parent and can add its own or override existing ones.
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self):
super().__init__() # Call parent init
self.layer = nn.Linear(10, 5)
def forward(self, x):
return self.layer(x)
This is how every custom PyTorch model works. Inheritance, polymorphism, and method overriding will be explored in depth in later articles.
Interactive: The OOP Landscape
Click on concepts in the concept map to explore their connections. Observe how class and object relate, how methods and attributes are defined and used — and where inheritance comes into play. Pay special attention to how many connections originate from the class node.
👆Click on a concept to learn more. The lines show how the concepts are connected.
Click on a circle to see details.
Legend
Class
Object
Method
Attribute
Inheritance
Key Takeaways
A class is a blueprint: it defines which attributes (data) and methods (behavior) every instance will have — but it is not an object itself in the everyday sense.
An object is a living instance of a class. You create it by calling the class name like a function: my_dog = Dog("Bello", "Labrador").
Each object has its own attribute values. Changing dog1.name does not affect dog2.name — they are independent copies of the blueprint.
__init__ sets up a new object's starting state. self refers to the specific object being created or used. Both are conventions, not magic.
AI libraries (PyTorch, Hugging Face, scikit-learn) are built on classes and objects. Learning to read .fit(), .predict(), .forward() as method calls on objects is the key to using them.
Quiz: Object-Oriented Programming
Question 1 / 4
Not completed
What is the difference between a class and an object?
1. What is the difference between a class and an object?
☐ A) A class is a concrete object in memory
☐ B) A class is a blueprint, an object is an instance of that blueprint
☐ C) An object defines methods, a class uses them
☐ D) Class and object are the same thing
2. What happens with this code?
class Dog:
def bark():
print("Woof!")
my_dog = Dog()
my_dog.bark()
☐ A) "Woof!" is printed
☐ B) SyntaxError
☐ C) TypeError: bark() takes 0 positional arguments but 1 was given
☐ D) NameError: Dog is not defined
3. dog1 = Dog("Bello"); dog2 = Dog("Rex"); dog1.name = "Wuffi". What is dog2.name?
☐ A) "Wuffi"
☐ B) "Rex"
☐ C) None
☐ D) Error
4. You read: clf = DecisionTreeClassifier(); clf.fit(X, y); clf.predict(X_test). What best describes this?
☐ A) Three independent function calls
☐ B) An object is created, then methods are called on that object
☐ C) Three different objects are created
☐ D) Inheritance from three classes
Answer Key: 1) B · 2) C · 3) B · 4) B
Checkpoint: Test Your Knowledge
What is the difference between a class and an object? In the Dog example with my_dog = Dog("Bello", "Labrador") — which is the class and which is the object?
Can two objects of the same class have different attribute values? Explain using the example where dog1.name = "Wuffi" but dog2.name stays "Rex".
When you write model = GPT2Model.from_pretrained("gpt2"): What role do import, the class definition, and the resulting model object each play?