2

Juliaで変更したい属性を持つPythonオブジェクト(JuliaのPyObject)をライブラリが返すPyCall.jlを介してPythonライブラリとインターフェースしようとしています。たとえば、次のダミーの 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境界でジュリアンに変換します。その自動変換をオプトアウトしたい場合は、文字列で醜いドットアクセスを使用できます:

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 の list-of-lists 表現内で作業できますが、かなり面倒です。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 に答える