HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Three implementations of observable objects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
threeimplementationsobjectsobservable

Problem

I wonder, what might be the best (most pythonic) way of implementing multiple observerables in Python. There are multiple objects, which should be able to register themselves at one or multiple observables.

Shall I simply submit the update methods, like this:

class MethodObservable():
    def __init__(self, data_source):
        self.observers = []
        self.data_source = data_source

    def add(self, callback):
        self.observers.add(callback)

    def remove(self, callback):
        try:
            self.observers.remove(callback)
        except ValueError:
            pass

    def notify():
        for callback in self.observers:
            callback(self.data_source)

class MethodObserver():
    def __init__(self, observer1, observer2):
        observer1.add(self.update_for_1)
        observer2.add(self.update_for_2)

    def update_for_1(self, data_source):
        # code

    def update_for_2(self, data_source):
        # code

data_source1 = SomeObject()
data_source2 = SomeOtherObject()
observable1 = MethodObservable(data_source1)
observable2 = MethodObservable(data_source2)
observer = MethodObserver(observable1, observable2)


Or is it better, to come up with a dictionary of classes and methods:

```
class DictObservable():
def __init__(self, data_source):
self.observers = {}
self.data_source = data_source

def add(self, observer, callback):
self.observers[observer] = callback

def remove(self, observer):
try:
del self.observers[observer]
except ValueError:
pass

def notify():
for callback in self.observers.values():
callback(self.data_source)

class DictObserver():
def __init__(self, observer1, observer2):
observer1.add(self, self.update_for_1)
observer2.add(self, self.update_for_2)

def update_for_1(self, data_source):
# code

def update_for_2(self, data_source):
# code

data_source1 = SomeObject

Solution

First thing, you should use new-style classes, inheriting from object. (Not necessary if you are in Python3, but convenient for backwards compatibility).

So, in short, your choices are:

  • Store them in a list



  • Store them in a dictionary



Of the two, the dictionary is the best option, because the keys are stored in a hash table, and you can look up items in O(1), whereas in the list you have to transverse the whole thing until you find it, so it is O(N).

Now, note that your dictionary implementation is a very thin layer on top of a dict. I would recommend inheriting from dict. If you are bound to the specific interface (.add, .remove) instead of the __setitem__ and pop, you can just create aliases. This can help you reduce the amount of code and also give you easier access to all the expresiveness of Python dicts.

Note that the third method is broken. In particular:

self.observers.add(observer)


when self.observers is a list, that doesn't have the method add.

Code Snippets

self.observers.add(observer)

Context

StackExchange Code Review Q#57804, answer score: 2

Revisions (0)

No revisions yet.