我用python为自己创建了一个简单的事件系统,我发现每次触发事件的方式基本相同:要么在调用结束时,要么在调用之前。我觉得作为一个装饰师这是件好事。下面是我使用的代码:
from functools import wraps
def fires(event):
"""
Returns a decorater that causes an `Event` to fire immediately before the
decorated function is called
"""
def beforeDecorator(f):
"""Fires the event before the function executes"""
@wraps(f)
def wrapped(*args, **kargs):
event.fire(*args, **kargs)
return f(*args, **kargs)
return wrapped
def afterDecorator(f):
"""Fires the event after the function executes"""
@wraps(f)
def wrapped(*args, **kargs):
result = f(*args, **kargs)
event.fire(*args, **kargs)
return result
return wrapped
# Should allow more explicit `@fires(event).uponCompletion` and
# `@fires(event).whenCalled`
afterDecorator.onceComplete = afterDecorator
afterDecorator.whenCalled = afterDecorator
return afterDecorator
有了这段代码,我可以成功地编写以下代码:
@fires(myEvent)
def foo(y):
return y*y
print func(2)
一切正常。当我试着写这个的时候问题来了:
@fires(myEvent).onceComplete
def foo(y):
return y*y
print func(2)
这给了我一个语法错误。对于复杂的装饰器有一些特殊的语法吗?解析器在第一组括号之后停止吗?你知道吗
我不确定是否有一种方法可以得到你想要的语法,但这里有一个替代方法。你知道吗
只需向
fires()
修饰符添加一个附加参数,以确定它应该发生在以下时间之前还是之后:然后像这样使用:
我添加了before和after变量的预计算(由于invoke技巧,所有闭包都是在导入时创建的,只要应用decorator就可以使用),使选择依赖于metadecorator的可选参数,并放入try/finally块以确保after事件始终触发。通过这种方法,函数属性的问题变得毫无意义。你知道吗
不,根据grammar specification,不可能:
装饰者必须在结尾加上括号
相关问题 更多 >
编程相关推荐