Python:通过lambda包装函数

neu*_*ont 0 python lambda decorator wrapper

我有一些代码

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')
Run Code Online (Sandbox Code Playgroud)

这将最终导致无限递归.在wrap_handler改为

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)
Run Code Online (Sandbox Code Playgroud)

该程序将变得正常.这是为什么?还有谁能告诉我更常用的功能包装方法?

Nik*_*s R 7

它以无限递归结束,因为lambda e: log_event(handler.handle, e)调用时,handler.handle已经是lambda表达式.log_event会调用lambdalambda会调用log_event等等.

要解决这个问题,只需将当前方法保存在本地范围内,这也不需要额外的lambda表达式.

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')
Run Code Online (Sandbox Code Playgroud)

你也可以使用装饰器.

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')
Run Code Online (Sandbox Code Playgroud)

C:\ Users \niklas\Desktop> foo.py使用以下方法
调用句柄:(EventHandler instance,'event'){}