I have a class that specifies a set of callback functions (shown here as cb1
and cb2
). I keep a map of these which I want to call after some event.
class Foo:
cb1 = None
cb2 = None
def test(self, input):
for (name, callback) in map:
if name == input:
if callback: callback()
...
map = {'one':cb1, 'two':cb2}
def mycallback():
print "mycallback()"
f = Foo()
f.cb1 = mycallback # Register our callback
f.test('one') # Nothing happens
Can you spot the problem?
What happens, is that when the class is initialized, the values of cb1
and cb2
(which are both None
) are copied into the map. So even after a user 'registers' the callback (by assigning to cb1
), the value in the map is still None
and nothing gets called.
Since there's no such thing as 'by reference' in Python, how do I remedy this?
Why not make your class explicitly handle registration?
import collections
class Foo(object):
handlers = None
def __init__(self):
self.handlers = collections.defaultdict(set)
def register(self, event, callback):
self.handlers[event].add(callback)
def fire(self, event, **kwargs):
for handler in self.handlers.get(event, []):
handler(**kwargs)
foo = Foo()
foo.register('one', mycallback)
foo.fire('one')
Add a registration function. In Foo class:
def register(self, name, cb): self.map[name] = cb
and instead of:
f.cb1 = mycallback
use:
f.register('one', mycallback)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With