1

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

为此,我使用 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

4

1 回答 1

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)

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

def script(event_type, priority):
    def decorate(func):
        return script.event(func, event_type, priority)
    return decorate
于 2013-10-13T14:23:16.710 回答