Reputation: 5657
Just want to know what's the common way to react on events in python. There are several ways in other languages like callback functions, delegates, listener-structures and so on. Is there a common way? Which default language concepts or additional modules are there and which can you recommend?
Upvotes: 26
Views: 24803
Reputation: 75427
Personally I don't see a difference between callbacks, listeners, and delegates.
The observer pattern (a.k.a listeners, a.k.a "multiple callbacks") is easy to implement - just hold a list of observers, and add or remove callables from it. These callables can be functions, bound methods, or classes with the __call__
magic method. All you have to do is define the interface you expect from these - e.g. do they receive any parameters.
class Foo(object):
def __init__(self):
self._bar_observers = []
def add_bar_observer(self, observer):
self._bar_observers.append(observer)
def notify_bar(self, param):
for observer in self._bar_observers:
observer(param)
def observer(param):
print "observer(%s)" % param
class Baz(object):
def observer(self, param):
print "Baz.observer(%s)" % param
class CallableClass(object):
def __call__(self, param):
print "CallableClass.__call__(%s)" % param
baz = Baz()
foo = Foo()
foo.add_bar_observer(observer) # function
foo.add_bar_observer(baz.observer) # bound method
foo.add_bar_observer(CallableClass()) # callable instance
foo.notify_bar(3)
Upvotes: 20
Reputation: 117018
I'm searching for an implementation to register and handle events in Python. My only experience is with Gobject, but have only used it with PyGtk. It is flexible, but might be overly complicated for some users. I have come across of few other interesting candidates as well, but it's not clear how exactly they compare to one another.
Upvotes: 0
Reputation: 100776
The matplotlib.cbook
module contains a class CallbackRegistry
that you might want to have a look at. From the documentation:
Handle registering and disconnecting for a set of signals and callbacks: signals = 'eat', 'drink', 'be merry' def oneat(x): print 'eat', x def ondrink(x): print 'drink', x callbacks = CallbackRegistry(signals) ideat = callbacks.connect('eat', oneat) iddrink = callbacks.connect('drink', ondrink) #tmp = callbacks.connect('drunk', ondrink) # this will raise a ValueError callbacks.process('drink', 123) # will call oneat callbacks.process('eat', 456) # will call ondrink callbacks.process('be merry', 456) # nothing will be called callbacks.disconnect(ideat) # disconnect oneat callbacks.process('eat', 456) # nothing will be called
You probably do not want a dependency to the matplotlib package. I suggest you simply copy-paste the class into your own module from the source code.
Upvotes: 0
Reputation: 3900
Most of the Python libraries I have used implement a callback model for their event notifications, which I think suits the language fairly well. Pygtk does this by deriving all objects from GObject, which implements callback-based signal handling. (Although this is a feature of the underlying C GTK implementation, not something inspired by the language.) However, Pygtkmvc does an interesting job of implementing an observer pattern (and MVC) over the top of Pygtk. It uses a very ornate metaclass based implementation, but I have found that it works fairly well for most cases. The code is reasonably straightforward to follow, as well, if you are interested in seeing one way in which this has been done.
Upvotes: 1
Reputation: 273486
It all depends on the level of complexity your application requires. For simple events, callbacks will probably do. For more complex patterns and decoupled levels you should use some kind of a publish-subscribe implementation, such as PyDispatcher or wxPython's pubsub.
See also this discussion.
Upvotes: 2
Reputation: 3182
I can't speak for common approaches, but this page (actual copy is unavailable) has an implementation of the observer pattern that I like.
Here's the Internet Archive link: http://web.archive.org/web/20060612061259/http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html
Upvotes: 2
Reputation: 16085
I have seen listeners and callbacks used. But AFAIK there is no Python way. They should be equally feasible if the application in question is suitable.
Upvotes: 0
Reputation: 18074
Personally, I've only seen callbacks used. However, I haven't seen that much event driven python code so YMMV.
Upvotes: 0