Python 3 Class Hiccup

(This is a legacy post from the old website.)

Today I was trying to implement the observer pattern in Python,
updating the observer with property methods, but my code was acting
wonky. Specifically, my setter wasn’t calling a method it was supposed
to be calling.

TL;DR version


If properties aren’t functioning like they should, ensure that your
classes are inheriting from object. Your classes don’t automatically
inherit from object (or the featured base class) in Python like in some
other languages (in python this is for the sake of backwards
compatibility). Use:

class MyClass(object):

instead of

class MyClass:

Long version


Here’s the basic observer pattern in Python (Notice not inheriting from object):

class ObjectOfInterest():
  def __init__(self):
    self.observers = []
    self._name = None

  def register_observer(self, observer):
    self.observers.append(observer)

  def _get_name(self):
    return self._name

  def _set_name(self, name):
    self._name = name
    self._update_observers()

  # I prefer this method of setting up properties over the @ syntax
  name = property(_get_name, _set_name)

  def _update_observers(self):
    for observer in self.observers:
    observer.update()

class Observer():
  def __init__(self, thing_to_watch):
    self.thing_to_watch = thing_to_watch
    self.thing_to_watch.register_observer(self)

  def update(self):
    print("updated.")

Pretty straight forward, right? However, _update_observers()
is never called. You will not see “updated.” printed to the console.
Everything seems like it’s working; the value of name is being updated.
So WTF?!

thing_to_watch = ObjectOfInterest()
observer = Observer(thing_to_watch)

print(thing_to_watch.name) # None

thing_to_watch.name = 'Bilbo'
print(thing_to_watch.name) # Bilbo

thing_to_watch.name = 'Frodo'
print(thing_to_watch.name) # Frodo

Remembering to inherit from object gets properties working right. Here
again is the code with output but this time my classes do inherit from
object and everything is right with the world.

thing_to_watch = ObjectOfInterest()
observer = Observer(thing_to_watch)

print(thing_to_watch.name) # None

thing_to_watch.name = 'Bilbo' # updated.
print(thing_to_watch.name) # Bilbo

thing_to_watch.name = 'Frodo' # updated.
print(thing_to_watch.name) # Frodo

This is a sloppy mistake that had me guessing for a good bit. Nothing was out of place and yet my results were borked.


I’ve found I occasionally run into an odd Vagrant error every now and then:

Leave a Reply

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