0

I am currently trying to implement the observer design pattern on a List class. The list class is the subject, and a calculate class is the observer. The calculate class needs to observe the list class, and calculate the sum of the values in the list in the list class. However, when the observer unsubscribes from the List, it is still getting the updates. And if the observer subscribes to a new list, the list before unsubscribing is still showing. Does anyone have any tips to why this happens?

from abc import ABCMeta, abstractmethod

class Observer(metaclass = ABCMeta):
    @abstractmethod
    def update(self, data):
        pass
    
class Subject(metaclass = ABCMeta):
    
    @abstractmethod
    def subscribe(self, observer):
        pass

    @abstractmethod
    def unsubscribe(self, observer):
        pass

    @abstractmethod
    def notify(self):
        pass


class List(Subject):
    
    def __init__(self):
        self.__list = []
        self._observers = set()
        
    def add(self, data):
        self.__list.append(data)
        self.notify()
        
    def subscribe(self, observer):
        self._observers.add(observer)
        
    def unsubscribe(self, observer):
        self._observers.discard(observer)
        
    def notify(self):
        for obs in self._observers:
            obs.update(self.__list)


class Calculate(Observer):
    
    def __init__(self, lst):
        self.__data = []
        self._list = lst
        self._list.subscribe(self)
        
    def update(self, data):
        self.__data = data
        
    def calculate(self):
        total = 0
        for item in self.__data:
            total += item
        return total
    
    def remove(self):
        self._list.unsubscribe(self)
        
    def attach(self, lst):
        self._list.subscribe(self)

So, this is my test and the output i get:

first_list = List()
first_list.add(1)
list_observer = Calculate(first_list)
first_list.add(5)
list_observer.calculate()

This returns 6, which is correct. However, when i do this:

list_observer.remove()
first_list.add(5)
list_observer.calculate()

I get 11. Which in sense, is the correct calculation, but since the observer unsubscribed, why is it still getting the updates? I also tried subscribing to a new list, but the old data is still in there.

pythonn00b
  • 57
  • 1
  • 8

1 Answers1

0

This has to do with the type of data you pass. The list of data is mutable. I can't explain it that well, but this answer is what you are looking for.

How do I pass a variable by reference?

You can fix it by doing this, you take a copy of the original object:

    def update(self, data):
        self.__data = data.copy()
DrummerMann
  • 692
  • 4
  • 9
  • I tried that, and it does fix the issue of no longer getting the update. However, if the observer subscribes to a different list, the old list is still there. – pythonn00b Jan 08 '22 at 02:10