Objects

Overview

In the previous lesson, you learned how to organize data using dictionaries by pairing keys with values. As programs become more complex, you may want to bundle both data and behavior together into a single, self-contained unit. In this lesson, you'll learn the basics of object-oriented programming (OOP) in Python — how to create your own custom data types called classes and bring them to life as objects.

Learning Objective

By the end of this lesson, you will have learned how to:

  • Understand the basics of object-oriented programming in Python.
  • Create simple classes and instantiate objects.

Key terms

Object-Oriented Programming (OOP): A programming paradigm that organizes code around objects — entities that combine data (attributes) and behavior (methods).

Class: A blueprint or template that defines the structure and behavior shared by all objects of that type.

Object (instance): A specific realization of a class, created using the class as a template. Each object has its own copy of the class's attributes.

Attribute: A variable that belongs to an object, used to store its data (e.g., a student's name or GPA).

Method: A function defined inside a class that describes the behavior of objects of that class.

__init__(): A special method (called a constructor) that Python automatically calls when a new object is created to initialize its attributes.

self: A reference to the current object instance, used inside methods to access the object's attributes and other methods.

Starter Code

This lesson encourages experimentation. Use the included Colaboratory notebook to run the code as you learn, or read the lesson and then freely experiment with the notebook's code.

Introduction

Everything in Python is an object. When you write "hello".upper(), you're calling a method on a string object. When you call scores.append(90), you're calling a method on a list object. Python's built-in types — strings, lists, dictionaries — are all classes under the hood.

Object-oriented programming lets you create your own types that work the same way. Instead of managing a student's name, GPA, and courses as separate variables, you can create a Student class that bundles all of that together in a clean, reusable package.

Defining a Class

Use the class keyword to define a class:

class Student:
    pass   # 'pass' is a placeholder — the class has no content yet

This creates a class called Student. The name follows the same rules as variable names, but by convention class names use PascalCase (each word capitalized, no underscores).

The __init__() Method

The __init__() method is the constructor — Python calls it automatically when you create a new object. Use it to set the initial values of the object's attributes:

class Student:
    def __init__(self, name, major, gpa):
        self.name = name
        self.major = major
        self.gpa = gpa
  • The first parameter is always self, which refers to the object being created.
  • self.name = name stores the argument name as an attribute on the object.

Creating Objects (Instantiation)

Create a new object by calling the class like a function:

student1 = Student("Alex", "Data Science", 3.8)
student2 = Student("Jordan", "Computer Science", 3.5)

Each object is an independent instance with its own attribute values.

Accessing Attributes

Use dot notation to access an object's attributes:

print(student1.name)    # Output: Alex
print(student1.major)   # Output: Data Science
print(student1.gpa)     # Output: 3.8

print(student2.name)    # Output: Jordan
print(student2.gpa)     # Output: 3.5

Defining Methods

Methods are functions defined inside a class. They describe what objects of that class can do:

class Student:
    def __init__(self, name, major, gpa):
        self.name = name
        self.major = major
        self.gpa = gpa

    def introduce(self):
        print(f"Hi, I'm {self.name} studying {self.major}.")

    def is_honors(self):
        return self.gpa >= 3.5

Call a method using dot notation on the object:

student1 = Student("Alex", "Data Science", 3.8)

student1.introduce()
# Output: Hi, I'm Alex studying Data Science.

print(student1.is_honors())
# Output: True

Updating Attributes

You can change an object's attributes after it has been created:

student1.gpa = 3.9
print(student1.gpa)    # Output: 3.9

You can also add methods that update attributes:

class Student:
    def __init__(self, name, major, gpa):
        self.name = name
        self.major = major
        self.gpa = gpa
        self.courses = []              # Initialize an empty list

    def enroll(self, course):
        self.courses.append(course)
        print(f"{self.name} enrolled in {course}.")

    def list_courses(self):
        if self.courses:
            print(f"{self.name}'s courses: {', '.join(self.courses)}")
        else:
            print(f"{self.name} has no courses yet.")
student1 = Student("Alex", "Data Science", 3.8)
student1.enroll("Python Programming")
student1.enroll("Statistics")
student1.list_courses()
# Output:
# Alex enrolled in Python Programming.
# Alex enrolled in Statistics.
# Alex's courses: Python Programming, Statistics

The __str__() Method

Define __str__() to control how an object is displayed when printed:

class Student:
    def __init__(self, name, major, gpa):
        self.name = name
        self.major = major
        self.gpa = gpa

    def __str__(self):
        return f"Student({self.name}, {self.major}, GPA: {self.gpa})"
student1 = Student("Alex", "Data Science", 3.8)
print(student1)
# Output: Student(Alex, Data Science, GPA: 3.8)

Without __str__, printing an object shows something like <__main__.Student object at 0x7f...>.

Putting It Together: A Data Science Example

Here's a class that represents a simple dataset column and includes methods for basic analysis:

class DataColumn:
    def __init__(self, name, data):
        self.name = name
        self.data = data

    def mean(self):
        return sum(self.data) / len(self.data)

    def max_value(self):
        return max(self.data)

    def min_value(self):
        return min(self.data)

    def count_above(self, threshold):
        return len([x for x in self.data if x > threshold])

    def summary(self):
        print(f"Column: {self.name}")
        print(f"  Count: {len(self.data)}")
        print(f"  Mean:  {self.mean():.2f}")
        print(f"  Min:   {self.min_value()}")
        print(f"  Max:   {self.max_value()}")


scores = DataColumn("Exam Scores", [88, 95, 72, 61, 84, 90, 78, 55, 93, 67])
scores.summary()
print(f"  Above 80: {scores.count_above(80)}")

Output:

Column: Exam Scores
  Count: 10
  Mean:  78.30
  Min:   55
  Max:   95
  Above 80: 4

Conclusion

In this lesson, you learned the fundamentals of object-oriented programming in Python: how to define a class with the class keyword, initialize objects with __init__(), store data in attributes, and define behavior through methods. OOP is a powerful way to organize complex programs, and you'll encounter it constantly as you work with Python's data science libraries — pandas DataFrames, scikit-learn models, and more are all built on classes and objects. In the next lesson, you'll put everything you've learned together in the module assessment.

Practice

Coding Assessment

Practice the concepts from this lesson using this Colaboratory notebook. After completing the exercises, save your notebook to GitHub and submit the link for grading.

Knowledge Check

Question 1: What is the purpose of the `__init__()` method in a Python class?

Question 2: What does `self` refer to inside a class method?

Question 3: What is the relationship between a class and an object?