Object-Oriented Programming (OOP)

Object-Oriented Programming (OOP)

Classes and objects

What Are Classes and Objects?

A class is a blueprint for creating objects — a way to bundle data and functionality together. For a broader overview, see Introduction to OOP.

An object is an instance of a class, representing a specific implementation of that blueprint. You’ll see these ideas in practice as you explore Classes and Objects in more depth.

Defining a Class

Defining a class creates a blueprint that can be used to instantiate objects. See more about this concept in Classes and Objects.

class Dog:
def __init__(self, name, breed):
self.name = name # attribute
self.breed = breed # attribute

def bark(self): # method
print(f”{self.name} says woof!”)

Key Parts:

  • __init: a constructor that runs when an object is created.
  • self: refers to the current object instance.
  • name and breed: attributes of the object.
  • bark: a method, a function that belongs to the class. See Advanced OOP Concepts.

Creating Objects (Instances)

dog1 = Dog(“Buddy”, “Labrador”)
dog2 = Dog(“Coco”, “Poodle”)

dog1.bark() # Buddy says woof!
dog2.bark() # Coco says woof!

Each object has its own state (data) and can use the class’s methods. For a broader context on encapsulation and how state is managed, see Encapsulation.

Accessing and Modifying Attributes

print(dog1.name) # Buddy
dog1.name = “Max”
print(dog1.name) # Max

Why Use Classes?

  • Encapsulation: bundle data + behavior.
  • Reusability: define once, create many objects.
  • Organization: keeps code clean and modular.
  • Extensibility: easy to expand with new methods or attributes.

For a deeper look at extensibility and how classes can be extended, see the Inheritance lesson.

Example with Behavior

class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance

def deposit(self, amount):
self.balance += amount

def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
else:
print(“Insufficient funds”)

account = BankAccount(“Alice”, 100)
account.deposit(50)
account.withdraw(30)
print(account.balance) # 120

For real-world applications of object-oriented patterns, see Practical Applications and Project.

Summary:

Concept Explanation
Class A template that defines the structure and behavior of objects (instances)
Object A concrete instance created from a class, with its own data and behavior
Attributes Variables that store object state (defined in __init__ as self.attribute)
Methods Functions defined within a class that operate on object data (always take self parameter)
__init__() Constructor method that initializes new objects (automatically called when creating instances)

Constructors (__init__)

What Is a Constructor?

A constructor is a special method in a class that’s automatically called when a new object (instance) is created. If you want a broader explanation of OOP concepts, see Introduction to OOP.

In Python, this constructor method is named __init__().

Purpose of __init__()

  • To initialize attributes (variables) of a new object.
  • To ensure each object starts in a well-defined state.
  • To optionally accept arguments during object creation.

Basic Syntax

class Person:
def __init__(self, name, age): # Constructor
self.name = name
self.age = age

  • self: Refers to the current instance.
  • name, age: Parameters used to set object-specific data.

Creating an Object

p1 = Person(“Alice”, 30)
print(p1.name) # Alice
print(p1.age) # 30

When Person(“Alice”, 30) is called:

  • Python creates a new Person object.
  • Calls __init__() with name=“Alice” and age=30.
  • Sets self.name and self.age.

Default Values

You can set default values for parameters:

class Person:
def __init__(self, name=”Unknown”, age=0):
self.name = name
self.age = age

Now you can call Person() with no arguments:

p2 = Person()
print(p2.name, p2.age) # Unknown 0

Points to Remember

Feature Description
Special method __init__ is automatically called when creating a new object instance
Self parameter Refers to the current object instance (must be first parameter in method definition)
Initialization Primary purpose is to initialize the object’s attributes and state
Default values Parameters can have default values to make them optional during instantiation
Not mandatory Can be omitted if no initialization logic is required (Python provides default)

To learn more about constructors and how they interact with subclassing, see the Inheritance lesson.

Without __init__

class Empty:
pass

e = Empty()

This still works — but the object won’t have any initialized attributes unless added manually.

Summary:

  • __init__ is Python’s constructor method, used to initialize object attributes.
  • It runs automatically when an object is created.
  • It makes your classes more flexible, dynamic, and useful.

For a broader look at constructors and class design in real projects, consult the Practical Applications and Project lesson.

Instance and class variables

What Are Instance and Class Variables?

Instance Variables are variables that are specific to each instance (object) of a class.

Class Variables are variables that are shared across all instances of the class. These are stored at the class level and have the same value for every object of the class.

1. Instance Variables

What Are They?

  • Instance variables are unique to each object. Every time a new object is created, it can have its own values for instance variables.
  • They are typically initialized inside the __init__() constructor.

Learn how Encapsulation helps manage access to these variables and protect object state in our Encapsulation lesson.

Example

class Dog:
def __init__(self, name, age):
self.name = name # instance variable
self.age = age # instance variable

dog1 = Dog(“Buddy”, 3)
dog2 = Dog(“Bella”, 5)

print(dog1.name) # Buddy
print(dog2.name) # Bella

In this case, name and age are instance variables because each dog object can have different values for these attributes.

2. Class Variables

What Are They?

  • Class variables are shared across all instances of the class.
  • They are typically defined inside the class but outside of any methods.
  • Class variables are often used for properties that should be common to all objects, such as a constant or counter.

Example

class Dog:
species = “Canine” # class variable

def __init__(self, name, age):
self.name = name # instance variable
self.age = age # instance variable

dog1 = Dog(“Buddy”, 3)
dog2 = Dog(“Bella”, 5)

print(dog1.species) # Canine
print(dog2.species) # Canine

# Changing class variable for the class
Dog.species = “Dog”

print(dog1.species) # Dog
print(dog2.species) # Dog

Warning:

Modifying a class variable using an instance (e.g., dog1.species = “New species”) will create an instance variable with that name, effectively shadowing the class variable.

Summary:

  • Instance Variables: Unique to each object; defined inside the __init__() method using self.
  • Class Variables: Shared by all objects of the class; defined directly in the class body.

For a deeper understanding of how class variables interact with inheritance and runtime behavior, see the Advanced OOP Concepts lesson.

Inheritance and polymorphism

What Is Inheritance?

Inheritance is a way to allow a new class (child class) to inherit attributes and methods from an existing class (parent class). This promotes code reuse and allows for creating more specialized classes based on general ones.

Key Concepts:

  • Parent Class (or Base Class): The class being inherited from.
  • Child Class (or Derived Class): The class that inherits from the parent class.

Example of Inheritance

# Par

Inheritance enables you to create specialized classes that reuse the code in a common base class. This pattern is often paired with polymorphism to allow different child classes to be treated the same way through a shared interface. For a deeper dive, see the Inheritance and Polymorphism lessons.

Scroll to Top