2

我正在尝试通过 PyCall.jl 与 python 库交互,其中该库返回一个 python 对象(Julia 中的 PyObject),其中包含我想在 Julia 中修改的属性。例如说我有以下虚拟 python 类,

import numpy as np

class MyNumpy:
     def __init__(self,n,m):
          self.array = np.zeros((n,m))
          self.size = (n,m)

现在在 Julia 中,我使用 PyCall.jl 加载这个 python 类并实例化,例如:

using PyCall

mynumpy = pyimport("MyNumpy.MyNumpy")
pyobject = mynumpy(3,3)
...

> pyobject.array
> 3×3 Array{Float64,2}:
  0.0  0.0  0.0
  0.0  0.0  0.0
  0.0  0.0  0.0
...

pyobject.array[1,1] = 1.0 

> pyobject.array
> 3×3 Array{Float64,2}:
  0.0  0.0  0.0
  0.0  0.0  0.0
  0.0  0.0  0.0

最后一行代码执行时没有任何错误,但是在调查后pyobject.array[1,1]该值没有改变(即,仍然是 0.0)。

例如,如何在 Julia 中完成更改 Pycall.jl PyObject 属性值,我可以使用指针来做到这一点,如果可以的话怎么办?抱歉,如果这很明显,但我没有运气,无法使用 PyCall.jl 文档弄清楚如何做到这一点。提前致谢。

PS 实际的python库不是可以轻易修改的。

4

1 回答 1

2

如果对象适当地嘎嘎作响,PyCall 默认会将对象转换为 Julia 类型。在这种情况下,当您访问类的array字段时会发生这种情况MyNumpy:它返回一个 numpy 数组,PyCall 会将其转换为Array边界处的 Julian。如果您想退出该自动转换,您可以使用带有字符串的更丑陋的点访问

julia> py"""
       import numpy as np

       class MyNumpy:
            def __init__(self,n,m):
                 self.array = np.zeros((n,m))
                 self.size = (n,m)
       """

julia> mynumpy = py"MyNumpy"
PyObject <class '__main__.MyNumpy'>

julia> pyobject = mynumpy(3,3)
PyObject <__main__.MyNumpy object at 0x1383398d0>

julia> pyobject.array # converted (copied!) into a Julian Array
3×3 Array{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> pyobject."array" # This is the "raw" numpy array!
PyObject array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

现在,您可以在 Python 的列表表示中工作,但这很烦人;API 不是最好的,您必须记住基于 0 的行主要实现。PyCall 有一个很好、方便的助手,它通过 Julian 将数组公开为共享内存AbstractArray

julia> array = PyArray(pyobject."array")
3×3 PyArray{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> array[1,1] = 1.0
1.0

julia> array
3×3 PyArray{Float64,2}:
 1.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> pyobject.array # remember, this is a copy
3×3 Array{Float64,2}:
 1.0  0.0  0.0
 0.0  0.0  0.0
 0.0  0.0  0.0
于 2019-11-04T17:46:16.223 回答