micheledpierri.com

Object-Oriented Programming (OOP) in Python

Lesson Objectives

By the end of this lesson, you will be able to:

  • Understand what Object-Oriented Programming is
  • Define and use classes and objects
  • Work with attributes and methods
  • Recognize when OOP is useful in analytical and ML code

This lesson introduces structure at scale:

from scripts and functions to cohesive software components.


What Is Object-Oriented Programming

Object-Oriented Programming (OOP) is a programming paradigm based on:

  • objects → entities that combine data and behavior
  • classes → blueprints for creating objects

Instead of passing data through many functions,

you group data + logic together.


Classes and Objects

Defining a Class

class Person:
    pass

  • class defines a new type
  • Person is the class name (CamelCase by convention)

Creating an object (instance):

p = Person()

p is now an object of type Person.


The __init__ Method (Constructor)

The __init__ method runs when an object is created.

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

Creating an instance:

p = Person("Michele", 40)

Here:

  • self refers to the current object
  • attributes are attached to the object

Instance Attributes

Attributes store data inside the object.

print(p.name)
print(p.age)

Each object has its own state:

p2 = Person("Anna", 35)

p and p2 are independent.


Methods (Object Behavior)

Methods are functions defined inside a class.

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

    def greet(self):
        return f"Hello, my name is {self.name}"

Calling a method:

p.greet()

Methods operate on the object’s internal data.


Why self Exists

self represents the current instance.

When you write:

p.greet()

Python translates it internally to:

Person.greet(p)

This is why self must always be the first parameter.


OOP vs Functions (When to Use What)

Use functions when:

  • logic is simple
  • data flows linearly
  • no persistent state is needed

Use classes when:

  • data and behavior belong together
  • state must be preserved
  • complexity grows

In data science:

  • functions → transformations
  • classes → models, datasets, pipelines

Simple Analytical Example

class Patient:
    def __init__(self, age, bmi):
        self.age = age
        self.bmi = bmi

    def risk_score(self):
        return self.age * self.bmi

Usage:

patient = Patient(65, 28.5)
patient.risk_score()

This pattern mirrors real analytical models.


Common Beginner Mistakes

Forgetting self

def greet():
    return "Hello"

This is not a method.

Putting logic outside the class

score = patient.age * patient.bmi

Better encapsulated as a method.


FAQ — Frequently Asked Questions

Q: Is OOP mandatory in Python?

A: No, but it becomes very useful as complexity increases.

Q: Is OOP slow?

A: No. Design quality matters more than micro-performance.

Q: Should I always use classes in data analysis?

A: No. Use them when structure and state are needed.

Q: What about inheritance?

A: Important, but intentionally postponed to advanced topics.


Exercises

Exercise 1

Define an empty class called Car.

Exercise 2

Create an object of class Car.

Exercise 3

Add an __init__ method with attributes brand and year.

Exercise 4

Create an instance of Car.

Exercise 5

Access the attributes of the object.

Exercise 6

Add a method age() that returns the car’s age.

Exercise 7

Predict the output:

class A:
    def __init__(self, x):
        self.x = x

a = A(5)
print(a.x)

Exercise 8

Explain why self is required.

Exercise 9

Write a simple class representing a dataset with a size attribute.

Exercise 10

Explain when OOP is useful in data analysis.


Solutions

Exercise 1

class Car:
    pass

Exercise 2

c = Car()

Exercise 3

class Car:
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year

Exercise 4

c = Car("Toyota", 2020)

Exercise 5

print(c.brand)
print(c.year)

Exercise 6

class Car:
    def __init__(self, brand, year):
        self.brand = brand
        self.year = year

    def age(self, current_year):
        return current_year - self.year

Exercise 7

# Output: 5

Exercise 8

# It refers to the current object instance

Exercise 9

class Dataset:
    def __init__(self, n_rows):
        self.n_rows = n_rows

Exercise 10

# OOP groups data and behavior, improving structure and reuse


Next Lesson Preview

In Lesson 11, we will cover:

  • list comprehensions
  • lambda functions
  • args and *kwargs
  • a first look at “Pythonic” code

This lesson will complete the transition from beginner to intermediate. systems.