Python Decorators in Education

Hello, Python enthusiasts!
I’m excited to share key concepts and examples of how Python decorators can simplify and enhance educational tasks.
Python decorators are useful for adding new functionality to existing functions or classes without changing their code. In education, decorators can be particularly helpful for managing tasks, such as tracking students, assignments, and grades. Here’s a beginner-friendly guide with examples to show how decorators work.
What Are Decorators?
A decorator is a function that "wraps" another function. It can add new functionality, like logging or repeating tasks, without altering the original function.
Basic Decorator Example
Let's begin with a basic example of division. Imagine the denominator is large, and we switch it with the numerator to do the calculation.
def div(a,b):
    print( a/b)
def wrapper(func):
    def inner(a,b):
        if(a<b):
            a,b=b,a
        return func(a,b)
    return inner
div=wrapper(div)
div(5,70)
Output:
14
Real-World Examples for Education
1. Repeat Decorator for Notifications
Imagine you want to send multiple reminders to students to submit assignments. A decorator can help you repeat a reminder without writing it multiple times.
def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                func(*args, **kwargs)
        return wrapper
    return decorator
@repeat(3)
def remind_student(name):
    print(f"Reminder: {name}, please submit your assignment!")
remind_student("Bharathi")
Output:
Reminder: Bharathi, please submit your assignment!
Reminder: Bharathi, please submit your assignment!
Reminder: Bharathi, please submit your assignment!
2. Singleton Decorator for a Single Gradebook
  • In a classroom, there should only be one gradebook. A decorator can ensure only one instance of it exists, even if we accidentally try to create multiple.
  • Provides a single access point for that instance, making it easier to manage and access shared resources across the application.
def single_instance(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper
@single_instance
class Gradebook:
    def __init__(self, subject):
        self.subject = subject
        self.grades = {}
# Test the singleton behavior
book1 = Gradebook("Math")
book2 = Gradebook("Science")
print(book1 is book2)
print(book1.subject)
print(book2.subject)
Output:
3. Property Decorators to Manage Student Grades
Property decorators make it easier to manage and control attributes. For example, let's create a Student class with a grade that can only be set within a valid range (0–100).
class Student:
    def __init__(self, name):  # Corrected the init method
        self._grade = None
        self.name = name
    @property
    def grade(self):
        return self._grade
    @grade.setter
    def grade(self, value):
        if 0 <= value <= 100:
            self._grade = value
        else:
            raise ValueError("Grade must be between 0 and 100.")
# Creating an instance and setting the grade
alex = Student("Alex")
alex.grade = 85
print(alex.grade)  #
Output
85
The @property decorator in Python allows you to define methods that behave like attributes, enabling controlled access to private instance variables. It provides a way to add validation or computation to attribute access without changing the syntax for the caller.
4. Method Decorator for Checking Permissions
Let’s say only a logged-in teacher can update student grades. A decorator can make sure this happens.
def require_login(func):
    def wrapper(self, *args, **kwargs):
        if self.logged_in:
            return func(self, *args, **kwargs)
        else:
            print("Only logged-in teachers can update grades.")
    return wrapper
class Teacher:
    def __init__(self, name):  # Corrected the init method
        self.name = name
        self.logged_in = False
    def log_in(self):
        self.logged_in = True
    @require_login
    def update_grade(self, student, grade):
        student.grade = grade
        print(f"{student.name}'s grade updated to: {grade}")
class Student:
    def __init__(self, name):  # Corrected the init method
        self._grade = None
        self.name = name
# Test the functionality
teacher = Teacher("Mrs. sasi")
student = Student("siva")
# Attempt to update the grade without logging in
teacher.update_grade(student, 90)  # Should print warning
# Log in and update the grade
teacher.log_in()
teacher.update_grade(student, 90)
This example shows how require_login only allows updates when the teacher is logged in.
Output:
Only logged-in teachers can update grades.
siva's grade updated to: 90
5. Timing Decorator to Track Assignment Check Time
If you’re checking many assignments, it’s useful to see how long each check takes. A timing decorator can help measure this.
import time
def time_it(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"Time taken: {end - start} seconds")
        return result
    return wrapper
@time_it
def check_assignments():
    time.sleep(2)  # Simulate checking delay
    print("Assignments checked.")
check_assignments()
Output:
Assignments checked.
Time taken: 2.0142056941986084 seconds
These examples show how decorators can be used in an educational setting, with simple names and concepts suitable for beginners.
Share this :

Leave a Reply

Your email address will not be published. Required fields are marked *