Jython Decorators:第一个arg无法强制转换为org.python.core.PyFunction

时间:2013-10-13 14:06:49

标签: java python decorator jython

我正在构建一种用Python编写CraftBukkit(Minecraft modded服务器软件)脚本的方法。

我通过使用Jython加载Python脚本,然后为事件添加装饰器等来完成此操作。

我目前正在实现事件装饰器,但是我遇到了一个问题:没有参数的装饰器工作正常,但是一旦我添加一个参数,就会开始抱怨没有足够的参数。

这有效:

@script.event
def test(event):
    print "hi" # Works

public void event(PyFunction func) {
    return func;
}

这不是:

@script.event("player.PlayerMoveEvent", "normal")
def test(event):
    print "player moved!" # TypeError: event(): 1st arg can't be coerced to org.python.core.PyFunction

public void event(PyFunction func, PyString eventType, PyString priority) {
    // Do all kinds of crap
    return func;
}

这是我的Java代码: http://pastebin.com/GsULYdJr

1 个答案:

答案 0 :(得分:0)

这与Jython无关。等效的纯Python代码显示了实际问题(为了简单起见,我省略了类或名称空间script):

def event(func, event_type, priority):
    # ...
    return func

@event("player.PlayerMoveEvent", "normal")
def test(event):
    print "player moved"

错误是

Traceback (most recent call last):
  ...
TypeError: event() missing 1 required positional argument: priority

这是由于对装饰者的误解造成的。您希望装饰函数定义像这样执行

def test(event):
    print "player moved"

test = event(test, "player.PlayerMoveEvent", "normal")

但它的执行方式如下:

__decorator = event("player.PlayerMoveEvent", "normal")

def test(event):
    print "player moved"

test = __decorator(test)

@背后的部分是单独评估的,而的结果是以test函数作为参数调用的。 Python中的常规修复是使用闭包,但这在Java中可能很麻烦。在Python中编写部分装饰器并保留当前的Java代码可能是最简单的:

def script(event_type, priority):
    def decorate(func):
        return script.event(func, event_type, priority)
    return decorate