14

この記事を読んで使用するときは、クラスとPythonからJavaへのマッピング(プロキシ)オブジェクトを含む完全なオブジェクト定義があることを前提としています。

クラス定義でラップせずに(上記のファクトリパラダイムを使用せずに)Pythonのコードの一部からメソッド(クラス内で定義されていないが、内部pythonクラスを使用)のみをインポートすることは可能ですか?

ある種のfrom myPyFile import myMethodJavaから実行してから、myMethodをJavaから直接使用する必要があります(おそらく静的メソッドとして?)?しかし、これが可能である場合、それをどのように行うかについての手がかりは見つかりませんでした(JavaにmyMethodの使用方法を指示するには、記事で説明されているインターフェイスのものがまだ必要な場合がありますか?)

よろしくお願いします。

編集:私は現在Jython 2.5.2を扱っているので、バージョンに依存し、将来的にははるかに簡単になる可能性がありますか?

編集:ダニエルへの返信で以下:

これがサンプルコードです。私が得たエラーを再現し、役立つ返信から実用的な例を取得します。

(そして、 yield -ed Python / Jythonの結果からJavaオブジェクトへのマッピングに戻るためのもう少し質問を追加します)

(@Joonas、申し訳ありませんが、コードを変更しましたが、以前のエラーに戻ることができなくなりました)

import org.python.core.Py;
import org.python.core.PyList;
import org.python.core.PyTuple;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

interface MyInterface {
    public PyList getSomething(String content, String glue, boolean bool);
}
class MyFactory {

    @SuppressWarnings("static-access")
    public MyFactory() {
        String cmd = "from mymodule import MyClass";
        PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState());

        PySystemState sys = Py.getSystemState();
        sys.path.append(new PyString("C:/jython2.5.2/Lib"));

        interpreter.exec(cmd);
        jyObjClass = interpreter.get("MyClass");
    }

    public MyInterface createMe() {
        PyObject myObj = jyObjClass.__call__();
        return (MyInterface)myObj.__tojava__(MyInterface.class);
    }

    private PyObject jyObjClass;
}


public class Main {

    public static void main(String[] args) {

    /*
// with only :
    PythonInterpreter interpreter = new PythonInterpreter();

     i get : 
Exception in thread "main" Traceback (most recent call last):
  File "<string>", line 1, in <module>
LookupError: no codec search functions registered: can't find encoding 'iso8859_1'

which is probably due to the : 
#!/usr/bin/env python
# -*- coding: latin-1 -*-

// yes i am from France, so my - sorry for that - bad english ;) and have to deal with non 127 ascii chars :)
     */

    PythonInterpreter interpreter = new PythonInterpreter(null, new PySystemState());

    PySystemState sys = Py.getSystemState();
    sys.path.append(new PyString("C:/jython2.5.2/Lib"));

    interpreter.exec("from mymodule import getSomething"); 
    PyObject tmpFunction = interpreter.get("getSomething"); 
    System.err.println(tmpFunction.getClass()); 
    MyInterface i = (MyInterface) tmpFunction.__tojava__(MyInterface.class); 
    System.err.println(i.getSomething("test", " - ", true));
    for (Object x : i.getSomething("test", " - ", true)) {
        System.out.println(x);
        // How can i get back an equivallent of the Python _"for (a, b) in getSomething:"_ 
        // with _"a"_ being PyUnicode or better String, and _"b"_ being boolean ?
    }

    // ^^ so adapting Daniel Teply solution works ! Thanks to him... 
    // BTW the part below did not work : but i may have missed or/and also mixed many things :/
    // i feel Jython damned hard to dive in :/ 
    // and really hope that the sample that i post and answers that i get will help others to swim!

    try {
        MyFactory factory = new MyFactory();
        MyInterface myobj = factory.createMe();

        PyList myResult = myobj.getSomething("test", " - ", true);
        System.out.println(myResult);
    }
    catch (Exception e) {
        System.out.println(e);
        // produce a : java.lang.ClassCastException: org.python.core.PySingleton cannot be cast to MyInterface
        // EDIT : see below last edit, this error may be due to my forgotten heritage from interface in the python code!
    }

    System.exit(-1);
    }
}

Pythonの部分:(mymodule.py)

#!/usr/bin/env python
# -*- coding: latin-1 -*-

class MyClass:
    def __init__(selfself):
        pass
    def getSomething(self, content, glue = '', bool = True):
        for x in range(5):
            yield (glue.join(map(str, (content, x, chr(97 + x))))), bool
        #return list()

def getSomething(content, glue = '', bool = True):
    print "test"
    myclass = MyClass()
    return list(myclass.getSomething(content, glue, bool))

def main():
    test()

if __name__ == "__main__":
    main()

編集

内側の質問(コメント内)について、部分的に自分自身に答えます:(
実際、私の答えとコードは醜いと感じますが、それは機能し、より良いJythonicの方法があるかどうかはわかりません。もしそうなら、私は本当に興味があります:))

for (Object x : i.getSomething("test", " - ", true)) {
    System.out.println(x);
    // How can i get back an equivallent of the Python _"for (a, b) in getSomething:"_ 
    // with _"a"_ being PyUnicode or better String, and _"b"_ being boolean ?

    // answering myself here :
    PyTuple mytuple = (PyTuple) x; // casting back x as PyTuple, can we have a java equivalent to _`(a, b) = x_ ? not sure...
    PyObject a = mytuple.__getitem__(0);
    PyObject b = mytuple.__getitem__(1);
    String aS = a.toString(); // mapping a unicode python string to java is as simple?
    boolean bB = b.toString().toLowerCase().equals("true");
    System.out.println(mytuple + "[" + aS + "][" + b + "][" + bB + "]");


編集:

「プロデュース:」に関する部分に自分自身に答えるjava.lang.ClassCastException:org.python.core.PySingletonはMyInterfaceにキャストできません...私の誤解とエラーのほとんどは、私が忘れていたという事実のためですPythonの部分からJavaを処理するために!(上記の私のコードを参照してください。これは私の主な質問ではなかったので、この事実については訂正せずに残します。実際の形式では、この主な質問についての実用的な答えです。ダニエルと私が理解するのを手伝ってくれたJoonas)。したがって、ファクトリパラダイムの場合、Pythonファイルに適切なインポートを追加することを忘れないでください

from testjython.interfaces import MyInterface #// defining method inside a MyInterface.java

class MyClass(MyInterface):
    [...]

私が抱えていたもう1つの問題は、インポートとパッケージを正しく処理することでした。ところで、このコードを上位のコードに追加すると、TypeErrorが生成されます:org.python.core.PyListに変換できませんが、これは別の懸念事項です...

4

2 に答える 2

7

を使用PyObject.__call__(Object... args)して、呼び出し可能なPythonオブジェクトを呼び出すことができます。例がpython従業員クラスを取得するのと同じ方法で、Java側から関数を表すPyFunctionを取得できます。

__tojava__(Interface.class)Alternativeleyでは、Pythonインタープリターから取得した関数を呼び出すことで、Java側の単一のメソッドインターフェイスの背後にこれを隠すことができます。詳細な例(実際にテスト済みです!):pythonファイル:

def tmp():
    return "some text"

java:

public interface I{
    public String tmp();
}

public static void main(String[] args) {
    PythonInterpreter interpreter = new PythonInterpreter();
    interpreter.exec("from test import tmp");
    PyObject tmpFunction = interpreter.get("tmp");
    System.err.println(tmpFunction.getClass());
    I i = (I) x.__tojava__(I.class);
    System.err.println(i.tmp());

}

出力:

class org.python.core.PyFunction
some text
于 2012-05-10T15:35:12.877 に答える
2

Javaでは、メソッド(または関数)はファーストクラスのオブジェクトではないため、メソッドのみをインポートすることはできません。つまり、最初にクラス(またはインターフェイス)を参照せずにメソッドを参照する方法はありません。静的メソッドでさえクラスに囲まれており、クラスオブジェクトを介してそれらを参照します。

ただし、Jython 2.5.2で導入されたソリューションにかなり近づくことができます。Jython関数は、単一の抽象メソッドJavaインターフェイスの実装として直接機能します(http://www.zyasoft.com/pythoneering/2010/09/jython-を参照)。 2.5.2-beta-2-is-released /)。したがって、Javaでインターフェースを定義できます。インターフェースにメソッド定義が1つだけ含まれていることが重要です。

interface MyInterface {
    int multiply(int x, int y);
}

さらに、Jythonでは次のようなものがあります。

myFunction = lambda x, y : x * y

MyInterfaceそれをJavaで使用します。リンク先の記事で説明されているように、Jython関数をJavaに取り込むには、何らかのファクトリパターンを使用する必要がありますが、このようなものは機能します(おそらくエラーが含まれていますが、アイデアはそうです)。

PyObject myFunction = interpreter.get("myFunction"); 
MyInterface myInterface = (MyInterface)myFunction.__tojava__(MyInterface.class);
int x = myInterface.multiply(2, 3); // Should return 6.
于 2012-05-10T09:52:07.020 に答える