我有一个包含类的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);
答案 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绑定在一起。