Object-Oriented Programming¶
By the end of this lesson you'll be able to:
- Define a class with
__init__(),self, attributes, and methods - Create class instances and access their attributes with dot notation
- Define a
__str__()method soprint()shows a useful description - Use inheritance and
super()to build subclasses that extend parent classes
You've been using objects all along — turtle, strings, lists, and dictionaries are all objects. Now it's time to create your own.
Welcome to Chapter 25!
You've used objects like Lego bricks — now you get to design your own bricks!
Object-oriented programming is how most large Python programs are organized.
Let's build something! Let's code it together!
Attributes and Methods¶
You already know that objects have attributes (data stored inside them) and methods (functions you call on them).
1 2 3 | |
Now you'll define your own objects.
The class Keyword¶
A class is a blueprint for creating objects.
Use class ClassName: followed by indented code that defines the class.
By convention, class names use CamelCase (each word capitalized, no underscores).
1 2 | |
__init__() — The Constructor¶
__init__() is the constructor — a special method Python calls automatically when you create a new instance.
It sets up the object's initial attributes.
self refers to the specific instance being created. Every method in a class takes self as its first parameter.
Before we define attributes, note that self.attribute_name = value stores a value inside the object:
Creating Instances and Dot Notation¶
Each time you call the class like a function, Python creates a new instance (a separate object from the same blueprint).
1 2 | |
Access attributes and methods with dot notation: fido.name, fido.bark().
What Do You Think Will Happen?
The code below creates two Student instances. Which student has the higher score?
What will the loop print for each one? Make your guess — then run it!
See It: Blueprint vs Real Dogs¶
What Do You Think Will Happen?
In the inspector below, the program defines class Dog and then calls
Dog(...) twice. Predict: when rex.bark() runs, how does Python know
which dog's name to print — Rex's or Bella's? Step through and watch
the orange arrow!
Explore the Object Instance Inspector MicroSim
The answer: self is always the object left of the dot. The class is just a dashed blueprint — the solid cards are the real objects, each with its own attribute boxes. The last step shows one more secret: rex.species is not on rex's card at all, so Python looks up to the blueprint, where the shared class variable lives.
__str__() — String Representation¶
__str__() defines what print(obj) and str(obj) show.
Without it, print(fido) shows something like <__main__.Dog object at 0x...> — not very helpful.
1 2 3 4 5 6 7 8 9 10 | |
__repr__() is similar but meant for developers — it should ideally show code you could paste to recreate the object.
Class Variables vs Instance Variables¶
An instance variable (defined with self.) belongs to one specific object.
A class variable (defined directly in the class body, not inside any method) is shared by all instances.
1 2 3 4 5 6 7 8 9 10 | |
Strings and Lists as OOP Examples¶
You've been using OOP all along — string and list methods are just methods on objects:
1 2 3 4 5 | |
Inheritance¶
Inheritance lets you create a new class (subclass) that inherits all the attributes and methods of an existing class (parent class).
Use class SubClass(ParentClass): to declare inheritance.
The super() function calls the parent class's __init__() so you don't have to repeat all its setup code.
Method Overriding¶
A subclass can override a parent method by defining a method with the same name. The subclass version runs instead of the parent's.
1 2 3 | |
See It: Watch the Method Lookup Climb¶
When you call d.eat() on a Dog, Python quietly searches: first in class Dog, and if the method is not there, up in class Animal. Before you click anything in the explorer below, predict: which of the three calls — d.fetch(), d.speak(), d.eat() — needs to climb up to Animal?
Explore the Inheritance Explorer MicroSim
Click all three calls and watch the highlights climb. Notice what happens after d.speak(): Animal's own speak() is marked shadowed — Dog's version won, exactly like the override example above. The last button shows super(), the polite way for a child class to run the parent's version anyway.
Learning Check¶
Your Turn — Add a Method
The Rectangle class below has width and height attributes but is missing two methods.
Add area() (returns width × height) and perimeter() (returns 2 × (width + height)).
Experiments¶
Try these changes. Predict what will happen first, then run it to check!
-
Add a
birthday()method to theDogclass that incrementsself.ageby 1. Call it twice and print the age. You'll know it worked whenfido.ageincreases by 2 after two birthday calls. -
Create a
Square(Rectangle)subclass where__init__only takessideand callssuper().__init__(side, side). You'll know it worked whenSquare(5).area()returns25. -
Add a
__repr__()toDogthat returnsf"Dog(name={self.name!r}, age={self.age})". You'll know it worked when usingrepr(fido)shows a reconstructable string. -
Create a class
BankAccountwithbalance = 0, adeposit(n)method, and awithdraw(n)method that refuses if the balance would go negative. You'll know it worked when withdrawing more than the balance prints an error and balance stays unchanged. -
Create a list of three
Studentobjects and sort them by score usingsorted(students, key=lambda s: s.score). You'll know it worked when the students appear in ascending score order.
OOP Expert!
You've learned to design your own objects with classes, inheritance, and special methods!
OOP is the foundation of almost all professional Python code — from web frameworks to game engines.
You're building real software skills. Let's keep coding!