![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
|
|
#1 |
|
Programming Guru
![]() |
<3 Decorators
After noting the power of Arevos' cache function, I wanted to see how decorators worked.
I <3 Decorators, very handy for applying a common transformation easily to your functions. It's a useful thing to learn, and very easy to understand once you see its logic. Here's one I made for my website def serveError(func_name, func_code, func_error):
return """<html>
<font face="courier new">
Server has encountered an error.<br />
<br />
Error <i>%s</i><br />
In Function <b><i>%s</i></b><br />
At <i>%s</i><br />
<br />
</font>
</html>"""%(func_error, func_name, func_code)
from sys import exc_info
def debug_wrapper(func):
"""If an error happens inside the function
it will be caught and appropriately acted upon."""
def new_func(*args):
try:
return func(*args)
except:
return serveError(func.func_name, func.func_code, exc_info()[0])
return new_func
@debug_wrapper
def foo():
raise KeyError
print foo()Any function I put "@debug_wrapper" before, will now display something other then a CherryPy error. ![]() Handy. Got any interesting ones? Edit: Here's Arevos' cache function: def cached(func):
"""Creates a cached function.
Cached function cannot handle keyword or mutable arguments."""
store = {}
def cached_func(*args):
if not store.has_key(args):
store[args] = func(*args)
return store[args]
return cached_func
@cached
def foo(x):
return len(x)
print foo("Hello World!") # calculates and prints 12
print foo("Hello World!") # prints 12 without calculating |
|
|
|
|
|
#2 |
|
The Oblivious One
Join Date: May 2005
Location: Ontario, Canada
Posts: 644
Rep Power: 4
![]() |
what does <3 mean? :p
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS! |
|
|
|
|
|
#3 |
|
Expert Programmer
Join Date: May 2005
Location: East Lansing, MI
Posts: 663
Rep Power: 4
![]() |
<3 = Love, notice the heart shape. That's one interpretation.
|
|
|
|
|
|
#4 |
|
Expert Programmer
Join Date: Jun 2005
Posts: 852
Rep Power: 4
![]() |
<3 = dropped my double scoop icecream cone
|
|
|
|
|
|
#5 |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
Multimethods spring to mind as one good use for decorators, and since a while ago we were talking about thread, here's a decorator that mimics the synchronized keyword in Java. I also find decorators quite useful for event based programming:
event_registry = {}
def listen_for(event_class):
if event_registry.has_key(event_class):
event_registry[event_class].append(func)
else:
event_registry[event_class] = [func]
def decorator(func):
def decorated(event):
return func(event)
return decorated
return decorator
def send_event(event):
if event_registry.has_key(event.__class__):
for func in event_registry[event.__class__]:
func(event)
class PokeEvent: pass
@listen_for(PokeEvent)
def poked(event):
print "Ouch!"
send_event(PokeEvent()) |
|
|
|
|
|
#6 |
|
Programming Guru
![]() |
Wow, that's seriously confusing... >.>
|
|
|
|
|
|
#7 |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
It may look it, but the principle is really rather simple - honest!
Event based programming works by getting functions to "listen out" for events. It's common technique in GUIs and computer games. For example, if I clicked a button, a "ButtonClick" event might be sent out: class Button:
def click(self):
send_event( ButtonClick(self) )@listen_for(ButtonClick):
def button_clicked(event):
print "The button you pressed was called: " + event.button_nameevent_registry = { ButtonClick : [button_clicked] } |
|
|
|
|
|
#8 |
|
Professional Programmer
Join Date: Feb 2005
Posts: 434
Rep Power: 4
![]() |
Arevos,
could you please send a working example?
__________________
I looked it up on the Intergnats! |
|
|
|
|
|
#9 |
|
Professional Programmer
Join Date: Apr 2005
Location: London, England
Posts: 459
Rep Power: 4
![]() |
That's pretty cool. I'm fonder of the maintenance free signal/slot implementation, however. Python cookbook at its best!
|
|
|
|
|
|
#10 |
|
Programming Guru
![]() Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5
![]() |
I prefer the dispatch method myself. It seems to me to be a more abstracted model, cleanly separating the concept of event handling and the events themselves.
As for a working example, I'll provide a simple one for demonstration purposes, though I'd advise using a library like pydispatcher instead. event_registry = {}
def connect(event_class, function):
"""Maps an event class to a function. Multiple functions can be mapped
to the same event class."""
try:
event_registry[event_class].append(function)
except KeyError:
event_registry[event_class] = [function]
def listen_for(event_class):
"""Decorator for the 'connect' function"""
def decorator(function):
connect(event_class, function)
return function
return decorator
def send_event(event):
"""Send an event to all functions that are listening for events of
that type."""
try:
functions = event_registry[event.__class__]
except KeyError:
return
for function in functions:
function(event)
def main():
"""Demonstration of how these events are used."""
class PokeEvent:
"""A generic event"""
def __init__(self, name):
self.name = name
@listen_for(PokeEvent)
def poked(event):
"""A function to be activated by an event"""
print "Ouch! I was poked by %s" % event.name
# Send a new PokeEvent. Should be caught by the "poked" function
send_event(PokeEvent("Fred"))
if __name__ == '__main__':
main()![]() |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|