Jython - 创建类实例的正确方法&从Python类执行方法

时间:2014-09-13 18:07:30

标签: java python jython

我有一个包含类的Python文件。我需要创建该类的实例,并能够通过Java调用方法。

我提出了这样的解决方案:

    PythonInterpreter r = new PythonInterpreter();
    r.execfile("File.py");


    PyObject p = r.eval("Car().begin()");
    System.out.println(p.toString());

和python代码:

class Car(SomeExtendedClass):

    myvar = 5

    def set(self, my):
        self.myvar = my;

    def begin(self):
        return self.myvar

现在,当我执行此操作时,它会打印5但是如果我运行以下代码:

    PyObject p = r.eval("Car().begin()");
    System.out.println(p.toString());

    r.eval("Car().set(7)");

    p = r.eval("Car().begin()");

    System.out.println(p.toString());

它仍会打印5,而不是7

看起来我没有创建Car的一个实例,它总是创建一个新实例,而不是使用创建的实例。

我是对的吗?

是否可以从Python文件中的类创建新实例,并使用Java调用/获取方法中的数据?

我尝试使用PyInstance加载eval(),但我无法从中加载异常:

return (PyInstance) this.interpreter.eval(className);

2 个答案:

答案 0 :(得分:3)

我刚刚找到了这个问题的解决方案"神秘"

首先,我们要执行我们要从中获取实例的python文件:

r.execfile("File.py");

然后定义将包含您要调用的类的PyObject

PyObject car = r.get("Car");

然后你必须调用__call__方法才能创建Car的新实例,并强制它到PyObjectDerived

PyObjectDerived p = (PyObjectDerived) o.__call__();

现在您可以调用方法,如下所示:

Python代码:

def set(self, my):
    self.myvar = my;

你的java电话:

p.invoke("set", Py.newInteger(5));

希望我帮助过任何人。

答案 1 :(得分:1)

每当你致电Car()时,你都会创建一个新的类实例。所以这会创建一个新对象并调用它的set方法:

r.eval("Car().set(7)");

但是这会创建另一个实例而不是操纵现有实例:

p = r.eval("Car().begin()");

r.eval("Car().begin()");的调用会根据需要创建一个新的python对象,但它实际上会返回对包含begin()方法返回值的python对象的引用 - 而不是创建的实例。这不是你想要的。

完全按照定义离开python类,此代码获取对类的单个实例的引用:

PyObject p = r.eval("Car()");

(正如您已经看到的,另一种方法是省略括号,它引用您对python类对象的引用,然后使用__call__创建实例)。

然后在现有实例上调用该方法:

p.invoke("set", Py.newInteger(7));

要获得修改后的值,因为它是实例的属性,并且不能通过“getter”获取。方法,PyObject类的 getattr 方法可以到达它(或者你可以在python代码中添加一个get方法):

System.out.println(p.__getattr__("myvar"));

很遗憾,一旦你通过p获得对象的引用,你就不能用java语法调用它上面的方法,但当然Java不知道这些方法和/或Python对象上可用的属性,即使它确实可以随时更改,因为Python的动态特性。因此,您可以使用invoke之类的方法将Java / Python绑定在一起。