Object-oriented Systems in Python, a Common Requirement

Introduction

When developing object-oriented systems in Python, a common requirement is to encapsulate behavior within classes in a way that balances readability, maintainability, and reusability. A typical scenario might involve designing an Employee class that includes a method to compute an employee’s salary. This method often requires both instance-level data (e.g., hours worked) and class-level constants (e.g., hourly rate). Understanding how to structure this setup correctly helps ensure your code adheres to clean coding principles.

In this article, we’ll explore the most appropriate way to design such a class using instance methods and class constants, and why it is the preferred approach.

Defining the Problem

Imagine you are building an Employee class. Each employee works a different number of hours, but the hourly rate is a fixed value shared across all employees. In such cases:

  • The number of hours worked is specific to each employee (instance-level data).
  • The hourly rate is the same for all employees (class-level constant).

You want the calculate_salary() method to compute salary using both these pieces of data.


Designing the Class

Here’s how you can structure the Employee class:

class Employee:
HOURLY_RATE = 20 # Class-level constant

def __init__(self, name, hours_worked):
self.name = name
self.hours_worked = hours_worked # Instance variable

def calculate_salary(self):
return self.hours_worked * Employee.HOURLY_RATE






Master Python: 600+ Real Coding Interview Questions
Master Python: 600+ Real Coding Interview Questions

  • If the hourly rate might differ across subclasses (e.g., for contractors), you could make it a class variable that’s override-able:
class Employee:
HOURLY_RATE = 20

def __init__(self, name, hours_worked):
self.name = name
self.hours_worked = hours_worked

def calculate_salary(self):
return self.hours_worked * self.__class__.HOURLY_RATE
  • Or, make it flexible via a parameter in the constructor if per-employee customization is needed.
Machine Learning & Data Science 600+ Real Interview Questions
Machine Learning & Data Science 600 Real Interview Questions

Why This Works

  1. Class Constant (HOURLY_RATE): Defining the hourly rate as a class variable makes it accessible to all instances of the class. It also allows easy modification at one place, improving maintainability.
  2. Instance Method (calculate_salary): Since salary depends on hours_worked, which is specific to each instance, calculate_salary must be an instance method (def with self). It accesses:
    • self.hours_worked → instance-level data
    • Employee.HOURLY_RATE → class-level constant
  3. Encapsulation and Readability: This structure maintains a clear separation of instance-specific data and shared constants, while encapsulating the logic for salary calculation in a single, intuitive method.
Master LLM and Gen AI: 600+ Real Interview Questions
Master LLM and Gen AI: 600+ Real Interview Questions

Conclusion

When designing methods like calculate_salary in an Employee class, it’s essential to distinguish between what varies per object (instance-level data) and what remains consistent (class-level constants). Using a class constant for the hourly rate and an instance method for the salary calculation is a clean and effective approach. It ensures your code is both modular and easy to maintain, making it easier for others (and your future self) to understand and extend. Properly structuring such patterns is a foundational skill in object-oriented programming.

Leave a Reply