Skip to content

Instantly share code, notes, and snippets.

Last active Jul 24, 2020
What would you like to do?
Observer pattern in Python, but has some annoying problems with respect to mypy typing
from typing import Any, Callable, Dict, List, Optional, Set
from abc import ABC, abstractmethod
import logging
LOGGER = logging.getLogger(__name__)
class Observer(ABC):
def update(self, observed: "Observable", event: Any) -> None:
class Logger(Observer):
def update(self, observed: "Observable", event: Any) -> None:
if isinstance(observed, "ImplementedThing") and isinstance(event, str):
LOGGER.warning(f"{observed.description} WARNING: {event}")
class Observable(ABC):
_default_observers: Set[Observer] = {Logger()}
_observers: Set[Observer]
def __init__(
using: Optional[List[Observer]] = None
self._observers = set()
for observer in Observable._default_observers:
if using:
for observer in using:
def subscribe(self, observer: Observer) -> None:
def unsubscribe(self, observer: Observer) -> None:
def publish(self, event: object) -> None:
for observer in self._observers:
observer.update(self, event)
class ImplementedThing(Observable):
description: str = "Hello World"
def __init__(self, description: str):
self.description = description
def implement(self):
thing = ImplementedThing("Goodbye")

This comment has been minimized.

Copy link
Owner Author

@MattOates MattOates commented Jul 24, 2020

With the above code we get the error: error: Argument 1 of "update" is incompatible with supertype "Observer"; supertype defines the argument type as "Observable" note: This violates the Liskov substitution principle note: See
Found 1 error in 1 file (checked 1 source file)

However if you attempt to resolve this its impossible to avoid a This violates the Liskov substitution principle which isn't strictly true as the more general class is an abstract class and can never be instantiated. So there is no substitution here strictly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment