I have some code like
class EventHandler:
def handle(self, event):
pass
def wrap_handler(handler):
def log_event(proc, e):
print e
proc(e)
handler.handle = lambda e: log_event(handler.handle, e)
handler = EventHandler()
wrap_handler(handler)
handler.handle('event')
that will end up with infinite recursion. While changing wrap_handler to
def wrap_handler(handler):
def log_event(proc, e):
print e
proc(e)
# handler.handle = lambda e: log_event(handler.handle, e)
handle_func = handler.handle
handler.handle = lambda e: log_event(handle_func, e)
the program will become OK. Why is that? And could anyone tell me more common ways to wrap functions?
It ends in an infinite recursion as when lambda e: log_event(handler.handle, e) is called, handler.handle is already the lambda expression. log_event would call the lambda and the lambda would call log_event, etc..
To fix this, just save the current method in the local-scope, this also does not need the additional lambda-expression.
class EventHandler:
def handle(self, event):
pass
def wrap_handler(handler):
proc = handler.handle
def log_event(e):
print e
proc(e)
handler.handle = log_event
handler = EventHandler()
wrap_handler(handler)
handler.handle('event')
You could also use a decorator.
def logging(function):
def wrapper(*args, **kwargs):
print "Calling %s with:" % function.__name__, args, kwargs
return function(*args, **kwargs)
return wrapper
class EventHandler:
@ logging
def handle(self, event):
pass
def __repr__(self):
return "EventHandler instance"
handler = EventHandler()
handler.handle('event')
C:\Users\niklas\Desktop>foo.py
Calling handle with: (EventHandler instance, 'event') {}
handler.handle = lambda e: log_event(handler.handle, e)
The anonymous function will, upon invocation, look up handler's handle member and pass that (along with e) to log_event. Because you immediately set handler.handle to the anonymous function, the anonymous function just gets a reference to itself.
This on the other hand:
handle_func = handler.handle
handler.handle = lambda e: log_event(handle_func, e)
Gets the handler's method once (specifically, you get a "bound method" object gluing the object and the underlying function object together), and only then you create the anonymous function and overwrite handler.handle.
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