self in Python references to variable rather than the class

Question:

So, I’m trying to code an observer pattern in Python.
Main method:

import Subject as Subj
import ConcreteStateA as Obs

Newsletter = Subj.Subject

Paul = Obs
Sara = Obs
Julien = Obs

print(Paul)
print(Sara)

Newsletter().addObserver(Paul)
Newsletter().addObserver(Sara)
Newsletter().addObserver(Julien)

Newsletter().notifyObservers("Bald ist Weihnachten!")

Newsletter().removeObserver(Paul)

Newsletter().notifyObservers("Der Nikolaus steht vor der Tür.")
class Subject:
    def __init__(self):
        self.ObserverList = []
    
    def addObserver(self, Observer):
        self.ObserverList.append(Observer)

    def removeObserver(self, Observer):
        self.ObserverList.remove(Observer)

    def notifyObservers(message, self):
        print("test")
        for obs in self.ObserverList:
            print("Notified Observer")
            obs.update(message)
import Observer

class ConcreteStateA(Observer.Observer):
    def Handle(msg, self):
        print(self.__name__ + "has received a message: " +self.msg)
        print(msg)

As far as I understand the self parameter, it references to it’s own instance. So if I type it in a Subject object, it would reference to that. Yet I get this error message:

AttributeError: 'str' object has no attribute 'ObserverList'

I don’t understand why it references to the message variable in an Subject method, shouldn’t it reference to the Newsletter (Subject class) object?

I tried to google my problem and read into the self parameter, yet without any success.
Everything I read seemed to support my theory, that the Newsletter object should be referenced, not the string message.

As I am fairly new to python there might be some other problems, i would be happy if you have other tips too 🙂

Asked By: Buschmxnn

||

Answers:

def notifyObservers(message, self):
        print("test")
        for obs in self.ObserverList:
            print("Notified Observer")
            obs.update(message)

The mistake is the way you define your parameters here. The fact is the first parameter will always be what you know as self – the Object. So by having a message as your first parameter, message will be used as the parameter for your object. e.g.: you could do message.ObserverList. Make sure to always have self as the first parameter.

So..

def notifyObservers(self, message):
        print("test")
        for obs in self.ObserverList:
            print("Notified Observer")
            obs.update(message)

and

class ConcreteStateA(Observer.Observer):
    def Handle(self, msg):
        print(self.__name__ + "has received a message: " +self.msg)
        print(msg)

should do the trick

Answered By: Noah
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.