python - Clojure Jython 互操作

标签 python interop lisp clojure jython

我想知道是否有人尝试以某种方式调用 Jython 函数 来自 Clojure 内部,如果是的话,你是如何着手去做的。我有 没有使用过 Jython,但我想 Jython 解释器可以 以与任何其他 Java 代码和 Python 程序相同的方式调用 可以在其中运行。但是我想知道是否有可能 以某种方式从 Clojure 调用单个 python 函数。就像我说的,我 还没有尝试过,所以它实际上可能很简单 明显的。我只是想知道是否有人尝试过这样做。

谢谢, 罗布

最佳答案

注释:我刚刚意识到这个问题特别是关于从 Clojure 调用 Jython 函数,不是关于构建一个成熟的 Jython-Clojure 互操作解决方案...但!我已经就我对后者的初步想法写了一篇小文章,我想无论如何这是合乎逻辑的下一步。我的意思是,在没有相当方便地访问 Python 类的情况下,您如何使用有趣的 Python 包?编写 Python 函数来包装方法调用等是一个可能的想法……但是一个可怕的想法。所以不管怎样,还是去吧。

要从 Clojure 中基本调用 Jython 执行的 Python 函数,请阅读此处下方的第二段和代码片段。然后阅读其余部分以获得乐趣和意想不到的 yield 。

我认为最初的体验远非无缝......事实上,我的预测是消除颠簸确实是一种皇家痛苦。不过,我有一种预感,它实际上比从 Java 调用 Jython 更容易。我只是多头 0.02 欧元...希望更有知识的人来告诉我我不知道我在说什么。 ;-)

首先要注意的是,Jython 将一切 包装在它自己的类中,所有这些都派生自org.python.core.PyObject。 , 懒得做 Python callables CallableRunnable等等。对于某些多方法/宏包装器,这实际上可能不是什么大问题。

Python 类可以从 Java 使用,但我(可能有缺陷)的理解是,通常情况下,当尝试对 Python 类的 Jython 实例进行操作时,Java 代码只会看到从 Java 基类或接口(interface)继承的方法。 .. 否则需要特殊格式的文档字符串(!)。这是 relevant page 的链接在 JythonWiki 上。 (不知道它有多新。)很酷的是,显然是 PyObjectDerived (用户定义的 Python 类的实例)可以被说服使用给定的参数调用它的方法。因此,通过勤奋的包装工作,人们可能希望能够使用稍微可以忍受的语法来完成它。

事实上,让我们看一些代码:

;; a handy instance of PythonInterpreter...
(def python (org.python.util.PythonInterpreter.))
(.eval python "5")
; -> #<PyInteger 5>

嗯,东西都包好了。一个有趣的 Clojuresque 解包器:

(defmulti py-wrap class)
;; but let's not wrap if already a PyObject...
(defmethod py-wrap org.python.core.PyObject [pyo] pyo)
(defmethod py-wrap Integer [n] (org.python.core.PyInteger n))
(defmethod py-wrap Long [n] (org.python.core.PyLong n))
(defmethod py-wrap BigInteger [n] (org.python.core.PyLong n))
(defmethod py-wrap String [s] (org.python.core.PyString s))

和上面的对应:

(defmulti py-unwrap class)
;; if unsure, hope it's not a PyObject at all...
(defmethod py-unwrap :default [x] x)
(defmethod py-unwrap org.python.core.PyInteger [n] (.getValue n))
(defmethod py-unwrap org.python.core.PyString [s] (.toString s))

函数:你可以.__call__他们,你可以._jcall他们。后一个选项更令人满意,因为它接受常规 Java 对象的 Java 数组,尽管它仍然返回 PyObject。 .前者采用适当数量的位置参数,这些参数应该已经 PyObject 了。秒。我不知道如何传递关键字参数……尽管 Jython 以某种方式做到了这一点,所以一定有办法。

这是 ._jcall 的超基本助手-类型调用:

(defn py-call [pyf & args]
  (apply (fn [pyf & args] (._jcall pyf (into-array args)))
         (map #(if (string? %) (py-eval %) %)
              (cons pyf args)))

您可以 .exec包含 fact 的 Python 定义的字符串, 然后做 (py-call "fact" 10)得到 #<PyInteger 5>背部;如果您愿意,请打开包装。

等等……我不知道的是:

  1. 需要什么样的努力才能使它足够有用以将有趣的 Clojure 代码与有趣的 Python 代码连接起来。
  2. 如果为调用 Python 提供合理的语法,是否需要做任何对性能非常不利的事情。

关于python - Clojure Jython 互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2129253/

相关文章:

c++ - 如何获得 boost 多精度数字部分?

c# - 从全局地址列表中提取电子邮件(不是姓名)

list - 如何理解 lisp 中的列表(cons 结构)

syntax-error - 汽车 : + is not a list, 口齿不清错误?

python - 用于 self 迭代 : what's in the list?

Python 脚本在控制台中运行但作为脚本出错

c# - Excel Interop - 效率和性能

python - Numpy 和 Scipy 在 Windows 上的安装

python - 如何从列中提取字符串的某些部分以在 Pandas 中创建其他列

按第二个对象排序缺点列表