Python:通过lambda包装函数
我有一些代码,比如Python:通过lambda包装函数,python,wrapper,decorator,lambda,Python,Wrapper,Decorator,Lambda,我有一些代码,比如 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
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')
这将以无限递归结束。将包装处理程序
更改为
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)
程序将变得正常。为什么呢?还有谁能告诉我更常见的包装函数的方法吗?因为函数是对象,所以不需要使用lambda将它们分配给变量。相反,你应该:
def wrap_handler(handler):
proc = handler.handle
def log_event(e):
print e
proc(e)
# handler.handle = lambda e: log_event(handler.handle, e)
handler.handle = log_event
在该代码中,避免在log_事件中计算handler.handle,因此不会发生递归
使用decorator更为常见,但decorator在内部也会做同样的事情。因为函数是对象,所以不需要使用lambda将它们分配给变量。相反,你应该:
def wrap_handler(handler):
proc = handler.handle
def log_event(e):
print e
proc(e)
# handler.handle = lambda e: log_event(handler.handle, e)
handler.handle = log_event
在该代码中,避免在log_事件中计算handler.handle,因此不会发生递归
使用decorator更为常见,但decorator在内部也会做同样的事情。它以无限递归结束,就像调用
lambda e:log\u事件(handler.handle,e)
时,handler.handle
已经是lambda表达式一样log\u event
将调用lambda,lambda将调用log\u 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')
你也可以用一个装饰师
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使用:(EventHandler实例,'event'){}调用句柄
当调用
lambda e:log_事件(handler.handle,e)
时,handler.handle
已经是lambda表达式,它以无限递归结束log\u event
将调用lambda,lambda将调用log\u 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')
你也可以用一个装饰师
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使用:(EventHandler实例,'event'){}调用句柄 在调用时,匿名函数将查找
处理程序的句柄成员,并将其(连同e
)传递给日志事件。因为您立即将handler.handle
设置为匿名函数,所以匿名函数只获取对自身的引用
另一方面:
handle_func = handler.handle
handler.handle = lambda e: log_event(handle_func, e)
获取处理程序的方法一次(具体地说,您将得到一个“绑定方法”对象,将对象和基础函数对象粘合在一起),然后才创建匿名函数并覆盖处理程序.handle
在调用时,匿名函数将查找处理程序的句柄成员,并将其(连同e
)传递给日志事件。因为您立即将handler.handle
设置为匿名函数,所以匿名函数只获取对自身的引用
另一方面:
handle_func = handler.handle
handler.handle = lambda e: log_event(handle_func, e)
获取处理程序的方法一次(具体地说,是一个将对象和底层函数对象粘合在一起的“绑定方法”对象),只有这样,您才能创建匿名函数并覆盖处理程序.handle
通常使用decorator包装函数…通常使用decorator包装函数…这将导致名称错误,因为没有名为e
的变量可用。此外,这将执行函数并分配其返回值,而不会分配整个函数。并且没有proc
(在log\u事件中调用)
。@yak:认真地说,请解释一下。这将导致名称错误,因为没有名为e
的变量可用。此外,这将执行函数并分配其返回值,而不会分配整个函数。而且没有proc
(在log\u事件中调用)
。@yak:认真地说,请解释一下。