• Labs icon Lab
  • Core Tech
Labs

Guided: Object-oriented Programming in Python

Build the skills you need to design structured, professional Python applications. In this hands-on lab, you’ll practice the core principles of object-oriented programming by creating custom classes, defining attributes and methods, and using inheritance to organize and extend functionality. Through practical examples like an HR Tracker for employees, a Scheduling Tracker for patient rooms, and a Notification System, you’ll see how OOP brings clarity and power to real-world applications. By the end, you'll be able to structure your code using proven techniques that make it more efficient, reusable, and ready for future growth. This lab is ideal for learners ready to move beyond basic Python scripts and start building real applications with confidence.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 1h 24m
Published
Clock icon May 15, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    Welcome to the Guided: Object-oriented Programming in Python Lab

    In this hands-on lab, you'll build a Python application using an object-oriented programming (OOP) approach. You'll learn how to structure your code using classes, attributes, and methods, and apply core OOP principles such as encapsulation, inheritance, polymorphism, and abstraction.

    By the end of this lab, you'll have experience designing and implementing a real-world system using custom classes and objects, and you'll understand how to model reusable and extensible code structures in Python.

    You'll progress through a series of steps that gradually build your understanding and skills with object-oriented Python.


    Step Overview

    Step 2: Define a Base Class

    In this step, you'll create a foundational Employee class that holds common data and behavior for all types of employees. You'll define instance attributes, implement a method, and learn how instance methods represent object-specific behavior. This step demonstrates the OOP principle of encapsulation by grouping related data and actions into a single class.

    Step 3: Create Subclasses with Inheritance

    Here, you'll define specialized subclasses like FullTimeEmployee and Intern that inherit from the base Employee class. You'll add unique attributes and override methods to reflect real-world differences. This step demonstrates the OOP principle of inheritance, where child classes reuse and extend the functionality of a parent class.

    Step 4: Demonstrate Polymorphism

    In this step, you'll interact with different employee types through a shared interface by calling the same method (get_contact_info) on each object. You'll also see how some behaviors, like checking whether an employee is a high earner, are specific to a subclass. This step showcases polymorphism, where objects of different types can be used interchangeably if they implement the same methods.

    Step 5: Design an Abstract Base Class to Define Shared Behavior

    You’ll formalize the shared structure across employee types by creating an abstract base class using Python’s abc module. This ensures all subclasses follow a common contract. You'll define an abstract method that each subclass must implement. This step demonstrates abstraction, which hides implementation details while exposing a clear, consistent interface across related classes.


    What You'll Learn

    • How to define and instantiate custom Python classes
    • How to add and access instance and class attributes
    • How to implement class methods and override behavior in subclasses
    • How to use inheritance and polymorphism to build reusable, flexible code
    • How to create abstract base classes that enforce shared structure

    You're ready to get started building a robust, object-oriented application in Python!


    Prerequisites

    You should have a basic understanding of Python, including how to write functions, instantiate variables, and understand the premise of classes. Familiarity with core object-oriented programming principles like encapsulation, abstraction, inheritance, and polymorphism is not required.

    Throughout the lab, you'll have the option to run the Python code provided in the Terminal tab to verify your task implementations for yourself. All commands should be executed from the workspace directory.

    Tip: If you need assistance at any point, you can refer to the solution directory. It contains subdirectories for each of the steps with example implementations.


  2. Challenge

    Define a Base Class

    Define a Base Class

    In this step, you'll define the foundation of your employee management system using object-oriented programming. You’ll start by creating a base class named Employee that includes attributes and behaviors shared across all employee types.

    Every class in Python should include an initializer method called __init__, which is automatically called when a new object is created. This method sets up the object’s initial state. Over the next few tasks, you'll add structure to the Employee class by implementing its initializer, defining instance attributes, and creating a method that returns employee-specific information.

    Methods on a class define the behavior of an object—what it can do or how it responds to specific operations. In Python, instance methods are defined inside a class and always take self as their first parameter. The self keyword refers to the specific object that is calling the method, allowing you to access and manipulate that object’s attributes.

    For example, when you define a method like get_contact_info, you use self.name and self.email to get the values that belong to that particular employee instance.

    def get_contact_info(self):
        return f"{self.name} can be reached at {self.email}"
    
    Instance Attributes and Instance Methods

    Instance attributes and instance methods belong to a specific object created from a class. When you create an object (also called an instance), that object has its own copy of the instance data defined in the __init__ method. You access these attributes and methods using dot notation on the object.

    For example:

    emp = Employee("Jalen Carter", 1001, "[email protected]")
    print(emp.name)                       # Accessing an instance attribute
    print(emp.get_contact_info()) # Calling an instance method
    

    Each instance of the class stores its own data, which means emp1.name and emp2.name can hold different values even though both are Employee objects.

    Class-level Attributes and Methods

    In contrast to instance variables and methods, class-level attributes and methods (also know as static attributes and methods) belong to the class itself and are shared across all instances. You typically call static methods on the class rather than an instance:

    Employee.company_name = "Pluralsight"
    print(Employee.company_name)
    

    This distinction helps organize data and behavior that is either unique to a specific employee or shared by the company as a whole.

    How Creating Classes Follows the Object-oriented Programming Principle of Encapsulation

    Encapsulation is the OOP principle of:

    • Bundling data (attributes) and methods (behavior) that operate on that data into a single unit—the class
    • Restricting direct access to some of an object's components to protect the internal state and reduce unintended interference

    So when you define a class like this:

    class Employee:
        def __init__(self, name, email):
            self.name = name
            self.email = email
    
        def get_contact_info(self):
            return f"{self.name} can be reached at {self.email}"
    

    You're encapsulating:

    • Data: name, email
    • Behavior: get_contact_info()

      That’s foundational encapsulation—you’re already practicing it!

      There are two types of encapsulation: basic and strong. The differences are explained below:

    | Type | Description | |-----------------------|-----------------------------------------------------------------------------| | Basic Encapsulation | Grouping data (attributes) and behavior (methods) inside a class | | Strong Encapsulation | Restricting access to internal data using naming conventions and controlled interfaces like getters and setters |

    In Python, this often looks like:

    class Employee:
        def __init__(self, name):
            self.__name = name  # private attribute
    
        def get_name(self):
            return self.__name
    

    Python doesn't enforce access control as strictly as other languages (like Java or C++), but the convention of using _ or __ underscores shows intent to encapsulate more tightly.

    ## Validation Script

    You can optionally validate your Employee class implementation is working correctly by running python3 employee_script.py in the Terminal. This script will prompt you to create an employee with input from the command line and will error if the employee could not be created. The script will tell you if the employee was created successfully and what the result of employee.get_contact_info() is.

  3. Challenge

    Create Subclasses with Inheritance

    Create Subclasses with Inheritance

    In this step, you'll extend your employee management system by creating specialized types of employees that inherit from the base Employee class.

    This introduces the object-oriented programming principle of inheritance. Inheritance allows you to define a general class with shared behavior, and then create more specific subclasses that reuse and extend that behavior. This helps reduce code duplication, organize logic more cleanly, and support future changes with minimal effort.

    You’ll create subclasses for different types of employees—like full-time workers and interns—and add attributes that are unique to those roles. Along the way, you'll see how Python’s super() function lets you call the parent class’s constructor, allowing each subclass to inherit and extend base functionality.

    This step demonstrates the object-oriented programming principle of inheritance. Inheritance allows you to define a general class with shared attributes and methods, then create specialized subclasses that reuse and extend that functionality. By building subclasses like FullTimeEmployee and Intern, you avoid repeating code and create a clear structure where common logic is defined once in the base Employee class and reused by its children. This promotes clean, maintainable, and scalable code. ## Validation Script

    You can optionally validate your FullTimeEmployee and Intern class implementations by running the following scripts in the Terminal:

    • python3 specific_type_of_employee_script.py
      This script allows you to create an employee of a specific type (e.g., Employee, FullTimeEmployee, or Intern) using command line input. It will display an error if the employee could not be created and will confirm successful creation if it works. The script also prints the result of calling get_contact_info() and the type of employee that was created. This is especially helpful for verifying that get_contact_info() is overridden correctly in the Intern class, and that object-specific attributes are displayed based on the employee type.

    • python3 full_time_employee_script.py
      This script specifically validates your FullTimeEmployee implementation. It prompts you to enter the required details to create a FullTimeEmployee object. After creation, it prints contact info, salary, and whether the employee is considered a high earner. This allows you to confirm that the is_high_earner() method works as expected: employees earning less than 100k are not high earners, while those earning 100k or more are.

    These scripts are a great way to manually confirm that your classes are working before moving on.

  4. Challenge

    Demonstrate Polymorphism

    Demonstrate Polymorphism

    In this step, you'll explore the object-oriented programming principle of polymorphism. Polymorphism allows different object types to respond to the same method call in ways specific to their class. This enables you to write flexible code that works across many different types of objects, as long as they implement a common interface or method.

    In Python, polymorphism is often seen when a method like get_contact_info() is defined in a base class, but overridden in subclasses like Intern. You can then loop through a list of mixed employee types and call get_contact_info() without needing to check which subclass each object belongs to—each one responds in its own way.

    In the tasks that follow, you'll:

    • Create a list containing objects of multiple employee types.
    • Call a shared method (get_contact_info) across all of them and observe different outputs.
    • Call a method that only exists on one subclass (is_high_earner) to demonstrate that certain behaviors are specific to object type.

    These tasks reinforce how polymorphism supports clean, extensible design by allowing objects to share method names while implementing their own behavior.

    Real-world Example of Polymorphism

    Think about a team meeting scheduler. You might loop through a list of FullTimeEmployee, Intern, and Contractor objects and call a method like get_availability() on each one. Even though the method name is the same, each employee type could define availability differently—full-time staff are available 9-5, interns only certain days, and contractors by appointment.

    This is polymorphism: writing code that works across many types, without knowing their exact class in advance.

    Bonus Material on Python and Duck Typing

    Duck typing and polymorphism are closely related, especially in dynamic languages like Python, but they aren’t exactly the same thing. Here’s how they connect:

    Polymorphism in object-oriented programming means that multiple types of objects can be used interchangeably because they implement the same behavior (e.g., they all have a get_contact_info() method). It’s about writing code that treats different classes through a shared interface or method name.

    Python also embraces a concept known as duck typing: “If it walks like a duck and quacks like a duck, it’s a duck”. In other words, Python focuses on whether an object supports a particular behavior, not what type it is. As long as an object has a method named get_contact_info(), Python will allow you to call it—no need to check if it’s an Employee, Intern, or anything else. Duck typing is Python’s way of achieving polymorphism without enforcing strict type hierarchies.

    With duck typing in Python, you do not have to inherit from a base class or implement an interface and as long as an object supports the expected method or behavior, you can use it in that context. This shifts the focus of whether or not you can use a method on a object away from type of object and to the behavior of the object.

    ## Validation Script

    You can optionally validate your implementation of the tasks above by running employee.py as a script. To do this, run the following command in the Terminal:

    python3 employee.py
    

    The output should include the contact information for the three employee objects you created, followed by their high earner status—if applicable. Only employees with a salary attribute (like FullTimeEmployee) should show a high earner result. Others will display a message indicating that they don’t have a salary attribute.

    This is a useful way to verify both polymorphic behavior and object-specific logic in your code.

  5. Challenge

    Design an Abstract Base Class to Define Shared Behavior

    Design an Abstract Base Class to Define Shared Behavior

    In this step, you'll apply the object-oriented programming principle of abstraction by creating an abstract base class to represent the shared structure and behavior of all employee types.

    Abstraction allows you to define a common interface for a group of related classes, while hiding or deferring the specific implementation details to those subclasses. It helps enforce consistency and keeps your codebase clean and extensible.

    Python provides support for abstraction through the abc module, which lets you define abstract base classes. These classes can include abstract methods—methods that must be implemented by any subclass. You can think of them as "promises" that any class inheriting from the base must fulfill.

    In this step, you'll:

    • Create a new abstract base class called AbstractEmployee.
    • Move shared attributes and methods into this class.
    • Add an abstract method that all subclasses must implement.
    • Update Employee, FullTimeEmployee, and Intern to inherit from AbstractEmployee instead of directly from object.

    After creating the AbstractEmployee base class, your other classes (Employee, FullTimeEmployee, Intern) must inherit from it. This ensures that all subclasses implement the required abstract methods and follow a common structure.

    This approach improves long-term maintainability, enforces a clear contract across related classes, and supports future extensions of your system.

    Supplemental Explanation on ABC and abstractmethod Modules

    Python provides the abc module (short for "Abstract Base Classes") to support abstraction in object-oriented programs. This module includes two key components:

    1. ABC: A special base class that you inherit from to define your own abstract base classes.
    2. @abstractmethod: A decorator used to mark methods that must be implemented by any subclass. If a subclass fails to define these methods, it cannot be instantiated.

    By using ABC and @abstractmethod, you create a blueprint for future classes, enforcing consistency while allowing each subclass to provide its own specific behavior.

    ## Final Validation

    To test your implementation of the abstract class and the required get_role_description() method, run the following script in the Terminal:

    python3 abstract_employee_script.py
    

    This script allows you to create any number of employees of different types using command-line input. After you've finished creating employees, it will print each one's type, contact information, and role description.

    Use this to confirm that:

    • All employee types are created successfully
    • get_contact_info() and get_role_description() work for each type as you expect
    • Inheritance and abstraction are functioning correctly across your class hierarchy
  6. Challenge

    Conclusion

    Conclusion

    Congratulations on completing the lab!

    You've now built a Python application using object-oriented programming principles from the ground up. Along the way, you:

    • Defined custom classes and created reusable object structures
    • Used instance and class attributes to manage data
    • Leveraged inheritance to avoid duplication and extend functionality
    • Applied polymorphism to interact with different objects through a common interface
    • Implemented abstraction using Python’s abc module to enforce consistent structure across related classes

    Together, these techniques form the foundation of professional, maintainable, and scalable Python code.

    You now have the tools to model real-world systems using object-oriented design—a critical skill in software development, whether you're building a single module or an entire application architecture.

    Ready to take it further? Try extending this lab with additional subclasses, custom methods, or even integrating with external data sources to simulate a more complete system. Happy coding!

Jaecee is an associate author at Pluralsight helping to develop Hands-On content. Jaecee's background in Software Development and Data Management and Analysis. Jaecee holds a graduate degree from the University of Utah in Computer Science. She works on new content here at Pluralsight and is constantly learning.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.