Observer Pattern in Python: Notify Listeners

Implement the Observer design pattern in Python with a Subject class that manages listeners and notifies them with messages.

Medium Python 3.9+ Aug 9, 2026 OOP & classes 12 views 0 copies

Python code

40 lines
Python 3.9+
class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self, message):
        for observer in self._observers:
            observer.update(message)


class Observer:
    def update(self, message):
        raise NotImplementedError


class EmailNotifier(Observer):
    def update(self, message):
        print(f"EmailNotifier received: {message}")


class SMSNotifier(Observer):
    def update(self, message):
        print(f"SMSNotifier received: {message}")


if __name__ == "__main__":
    subject = Subject()

    email = EmailNotifier()
    sms = SMSNotifier()

    subject.attach(email)
    subject.attach(sms)

    subject.notify("System update available")

Output

stdout
EmailNotifier received: System update available
SMSNotifier received: System update available

How it works

The Subject maintains a list of observers and exposes attach/detach methods to manage them. When notify is called, it iterates over the list and invokes each observer's update method, allowing decoupled communication. The Observer base class defines an abstract update method that subclasses must implement, ensuring a consistent interface.

Common mistakes

  • Forgetting to detach observers, causing memory leaks or duplicate notifications
  • Not catching errors in one observer's update that break the whole notification loop
  • Mutating the observer list while notifying (e.g., detaching during iteration)
  • Using a set instead of a list if you need multiple instances of the same observer type

Variations

  1. Use a WeakSet to store observers if they are short-lived objects
  2. Pass different event types as arguments to update for more granular handling

Real-world use cases

  • Event-driven user interface frameworks where UI components subscribe to model changes
  • Pub/sub systems in microservices to broadcast domain events to multiple services
  • Notification pipelines that push alerts to email, SMS, and logging sinks when metrics cross thresholds

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.