Reputation: 20
I have a Python class that allows a user to register a callback. I am trying to provide a default callback but I'm not sure how to do it.
First attempt:
class MyClass:
callback = printing_callback
def register_callback(self, callback):
self.callback = callback
def printing_callback(self, message):
print(f"Message: {message}")
def notify(self, message):
self.callback(message)
This gave me an 'unresolved reference' error for printing_callback
Second attempt:
I tried changed the line to callback = self.printing_callback
. This gave me an 'unresolved reference' error for self
Third attempt:
callback = lambda message: print(f"Message: {message}")
which gave me this warning: "PEP 8: E731 do not assign a lambda expression, use a def"
Is there a way to initialize callback to a default?
Update
I found a way to set the default method and that is not to have printing_callback
be an instance method - which makes sense. This appears to compile without warnings
def printing_callback(message):
print(f"Message: {message}")
class MyClass:
callback = printing_callback
def register_callback(self, callback):
self.callback = callback
def notify(self, message):
self.callback(message)
But now the when printing_callable
is called it is called with an extra argument - the MyClass
instance that called it.
I can change the signature to printing_callback(myClass, message)
and the code works. Are there cleaner ways to do this than to just have an extra parameter?
Upvotes: 0
Views: 109
Reputation: 33107
Set the default on initialization.
def printing_callback(message):
print(f"Message: {message}")
class MyClass:
def __init__(self, callback=printing_callback):
self.callback = callback
def notify(self, message):
self.callback(message)
As far as I can tell, there's no reason for callback
to be a class attribute, so make it an instance attribute, and that avoids it being registered as a method.
If you need to change it later, you can simply change the callback
attribute instead of using the setter register_callback()
:
m = MyClass()
m.notify('Hello!') # -> Message: Hello!
m.callback = print
m.notify('Hi!') # -> Hi!
Upvotes: 2
Reputation: 16526
In first attempt, it's obvious that you have no reference to printing_callback
, you didn't define it.
In second: self
parameter is which get filled by python, when you call that method on an instance of the class. It points to the newly created object which is the class instance ofcourse. note that it is local to the methods, not inside the body of your class. so no reference again.
The structure you are looking for is :
def printing_callback(self, message):
print(f"Message: {message}")
class MyClass:
callback = printing_callback
def register_callback(self, callback):
self.callback = callback
def notify(self, message):
self.callback(message)
obj = MyClass()
obj.callback("testing")
Note I added an extra parameter self
(the actual name doesn't matter).This is because we call that function on an instance, so again python fill the first argument with the reference to that instance. This is why I named it self
.
Upvotes: 0