我正在try Graalvm非常酷的Polyglot特性,这样我就可以从Scala应用程序判断Python.

测试REPL代码如下.如果我运行它,并输入以下代码,我可以很好地计算v.__add__(1).我明白了:

>>> v
evaluating v
evaluated got Value(7)
>>> v.__add__(1)
evaluating v.__add__(1)
evaluated got Value(8)
>>> 

有没有办法判断v + 1? 当我try 的时候,我得到TypeError: unsupported operand type(s) for +: 'foreign' and 'int'分.

以下是测试REPL代码:

import org.graalvm.polyglot.{Context, Source}

import scala.annotation.targetName
import scala.util.control.NonFatal

case class Value(v: Int) {
  @targetName("__add__")
  def +(i: Int): Value = Value(v + i)
}

class Python(context: Context, v: Value) {
  private val language = "python"

  context.getBindings(language).putMember("v", v)

  def eval(code: String): AnyRef = {
    try {
      val source = Source
        .newBuilder(language, code, "<shell>")
        .interactive(false)
        .buildLiteral()

      println(s"evaluating $code")
      val res = context.eval(source)
      println(s"evaluated got $res")
      res
    } catch {
      case NonFatal(e) =>
        println(s"error evaluating $code")
        e.printStackTrace()
        null
    }
  }
}

object Python {
  def main(args: Array[String]): Unit = {
    val context = Context
      .newBuilder("python")
      .allowAllAccess(true)
      .build()

    val python = new Python(context, Value(7))

    while (true) {
      val line = scala.io.StdIn.readLine(">>> ")
      python.eval(line)
    }
  }
}

推荐答案

在这一点上,GraalPy不允许覆盖这样的Python"魔术"方法."外来"对象获得类"外来",它以一种他们称之为适当的较低级别Truffle interop messages的方式来defines个那些"魔术"方法.您可以这样看到它们:

>>> dir(type(x))
['__add__', '__and__', '__bases__', '__bool__', '__call__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__divmod__', '__doc__', '__eq__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__instancecheck__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__next__', '__or__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmul__', '__ror__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__truffle_richcompare__', '__xor__']

问题是您的对象的Python类型不是Java/Scala类,而是"外来的".您定义的方法和字段是属于对象实例的Python属性,但是像+这样的操作的"魔术"方法是在type=>;"foreign"类型上查找的.另请参见https://github.com/oracle/graalpython/issues/249.

目前,虽然您可以在Scalar/Java端实现较低级别的Truffle互操作消息,但我实际上建议从"其他"端try 这样做.您可以定义包装Scala/Java对象的Python类,并适当地实现"魔术"方法:

class ScalaWrapper:
    def __init__(self): self.delaget = delegate
    def __add__(self, other): delegate.__add__(other)

您可以按照以下方式从Scala/Java实例化它:

Value wrapperInstance = context.getBindings("python").getMember("ScalaWrapper").newInstance(myScalaObjToBeWrapped);

或者,您也可以在Python中实例化它.

Python相关问答推荐

删除最后一个pip安装的包

pandas滚动和窗口中有效观察的最大数量

如何在Django基于类的视图中有效地使用UTE和RST HTIP方法?

为什么NumPy的向量化计算在将向量存储为类属性时较慢?'

从Windows Python脚本在WSL上运行Linux应用程序

网格基于1.Y轴与2.x轴显示在matplotlib中

如何使用使用来自其他列的值的公式更新一个rabrame列?

BeautifulSoup:超过24个字符(从a到z)的迭代失败:降低了首次深入了解数据集的复杂性:

从源代码显示不同的输出(机器学习)(Python)

判断Python操作:如何从字面上得到所有decorator ?

使用python playwright从 Select 子菜单中 Select 值

使用polars. pivot()旋转一个框架(类似于R中的pivot_longer)

使用np.fft.fft2和cv2.dft重现相位谱.为什么结果并不相似呢?

PYTHON中的pd.wide_to_long比较慢

随机森林n_估计器的计算

在任何要保留的字段中添加引号的文件,就像在Pandas 中一样

对当前的鼹鼠进行编码,并且我的按键获得了注册

将索引表转换为Numy数组

了解如何让库认识到我具有所需的依赖项

使用元组扩展字典的产品挑战