LoginSignup
1
0

More than 1 year has passed since last update.

juliaの型でpythonオブジェクトをラップするときのテクニック

Last updated at Posted at 2022-01-30

juliaの型でpythonオブジェクトをラップするときのテクニック

いきなりだが、juliaでpythonパッケージをpyimportしてラップしたものを使う際に、hoge.pyobj~のように間にpyobjをうたないといけない。
本記事ではpyobjの入力を省略するテクニックを紹介する。

通常の場合

using PyCall

numpy = pyimport("numpy")

struct Hoge
    pyobj::PyObject
end

これを実行すると

hoge = Hoge(numpy)
hoge.pyobj.sqrt(2) #この例のようにいちいちpyobjを打たないといけない

これを以下のようにpyobjを省いて実行するのが本記事のゴールである。

hoge.sqrt(2)

コードは以下のようになる。

using PyCall

numpy = pyimport("numpy")

struct Hoge
    pyobj::PyObject
end

function Base.getproperty(h::Hoge, s::Symbol) #構造体を引数に保つ関数!
    if s == :pyobj
        getfield(h, s)
    else
        getproperty(getfield(h, :pyobj), s)
    end
end


実行

hoge = Hoge(numpy)

# Case1
hoge.sqrt(2) #1.4142135623730951

#Case2
hoge.pyobj.sqrt(2) #上と同じ結果

何が起こっているのか

Case1の場合

結論から言うと、hoge.sqrtは、getproperty(hoge, :sqrt) と同じである(言い換えると、hoge.sqrt(2)は、getproperty(hoge, :sqrt)(2)と同じ)。

まず、hoge.sqrtが実行されると内部でBase.getproperty関数が呼び出される。Base.getpropertyの引数には、それぞれ第一引数hにhoge、第二引数sにsqrtが対応する。
s == :pyobjはFalseなので、getpropertyが呼びだれることになる。
ここで、getfield(h, :pyobj) は、Hogeのフィールドのpyobj,ここではnumpyに対応する。
(getfield(hoge, :pyobj)を実行するとわかります。)

従って、getproperty(getfield(h, :pyobj), s)とは、numpy.sqrtを実行していることになる。

Case2の場合

hoge.pyobjでBase.getproperty関数が呼び出される。Base.getpropertyの引数には、それぞれ第一引数にhoge、第二引数にpyobjが対応する。
s == :pyobjがTrueなので、getfield(h, s)が実行される。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0