to access Python objects in Java using Jython, it's necessary to create a Java interface and use coersion (PyObject.__java__()) to assign the object to a Java reference. (http://www.jython.org/faq2.html)
The problem is that the Python library I'm trying to use does not have gets and sets, and I don't want to change the library code if I can.
Is there a way to get those public variables without having to implement Python classes to subclass and expose those attributes through methods?
Thanks.
-
While waiting for this, I developed a library to facilitate the coercion without having to alter the library to subclass the interfaces. It also facilitate the creation of separate python classes that subclass the original and can expose the attributes. It's here: github.com/danielgimenes/jythonEasierCoerciondgimenes– dgimenes2014年03月15日 16:14:35 +00:00Commented Mar 15, 2014 at 16:14
1 Answer 1
You can access the attributes from a PyObject directly by using the __getattr__(PyString) and __setattr__(PyString, PyObject) methods.
You can get an attribute with:
PyObject pyObject = ...;
// Get attribute: value = getattr(obj, name)
// OR: value = obj.__getattr__(name)
PyString attrName = Py.newString("some_attribute");
PyObject attrValue = pyObject.__getattr__(attrName);
- WARNING: Make sure to use
__getattr__(PyString)because__getattr__(String)only works for interned strings.
You can also set an attribute with:
PyObject pyObject = ...;
// Set attribute: setattr(obj, name, value)
// OR: obj.__setattr__(name, value)
PyString attrName = Py.newString("some_attribute");
PyObject attrValue = (PyObject)Py.newString("A string as the new value.");
pyObject.__setattr__(attrName, attrValue);
NOTE: The value does not have to be a
PyString. It just has to be aPyObject.WARNING: Make sure to use
__setattr__(PyString, PyObject)because__setattr__(String, PyObject)only works for interned strings.
Also, you can call a python method using __call__(PyObject[] args, String[] keywords):
PyObject pyObject = ...;
// Get method: method = getattr(obj, name)
// OR: method = obj.__getattr__(name)
PyString methodName = Py.newString("some_method");
PyObject pyMethod = pyObject.__getattr__(methodName);
// Prepare arguments.
// NOTE: args contains positional arguments followed by keyword argument values.
PyObject[] args = new PyObject[] {arg1, arg2, ..., kwarg1, kwarg2, ...};
String[] keywords = new String[] {kwname1, kwname2, ...};
// Call method: result = method(arg1, arg2, ..., kwname1=kwarg1, kwname2=kwarg2, ...)
PyObject pyResult = pyMethod.__call__(args, keywords);
- NOTE: I cannot explain why the keyword names are
Stringhere when getting an attribute by name requiresPyString.