pythonコードをjuliaへ移植したい
本記事は、julia初学者の視点で、既存のpythonコードをjuliaに書き写す方法について書きました。
特に、プログラミング初学者にとって、juliaにはpythonのようなclassがなく、どのようにしたらpythonコードをjuliaに移植できるのか、と悩む人が多いかと思ったので、その方法について書きました。
structのメリット
本題に入る前に、基礎事項であるstructの使い方を簡単に紹介します。
structは、オリジナルの型のことであり、そのメリットは、自ら定義した型に対して、演算が実行できることにある。
例えば自分で定義したオリジナルの型に対してベクトルの加法をしたい場合
struct Point
x::Float64 #x, yをfieldと呼ぶらしい。
y::Float64
end
function Base.:+(p::Point, q::Point)
return Point(p.x + q.x, p.y + q.y)
end
実行
p = Point(1.0, 1.0)
q = Point(2.0, 3.0)
Base.:+(p, q) # Point(3.0, 4.0)
#以下と同じ
+(p, q) # Point(3.0, 4.0)
上記の例では、自分が決めたオリジナルの型(x,yというFloat64の型を持つデータ構造)に対して、ベクトルの加法を実行した。
例1:
以下pythonコードとjuliaコードを比較しながら、pythonコードをjuliaに移植する時のチップスをまとめる。
python
import random
class Mouse:
def __init__(self, cry):
self.cry = cry
def greet(self):
return self.cry
def encode(self, msg):
print(self.greet())
ret = ""
for m in msg:
ret += random.choice(["chu", "kyu"])
return ret
実行
h = Mouse("cyu-")
h.greet()
h.encode("おはようございます")
julia
-
juliaの構造体(struct)にはデータしか入らないため、pythonでいうclassのメソッドはない。
-
juliaでは、pythonのメソッド的なものを定義するために、juliaの関数の第一引数に構造体を入れることでメソッドに対応するものを作り出す
-
この第一引数に入れた構造体こそが、pythonのメソッドの第一引数に入るselfに対応
struct Mouse
cry
end
function greet(self::Mouse) #functionの引数に構造体を代入する。
return self.cry
end
function encode(self::Mouse, msg) #第一引数がselfに対応
println(greet(self))
ret = ""
for m in msg
ret *= rand(["chu", "kyu"])
end
return ret
end
実行
m = Mouse("chu-")
greet(m)
encode(m, "oha")
例2:モンテカルロ
もう1つ例を見る。
python
import numpy as np
class Monte:
def __init__(self, n):
self.n = n
def calc_pi(self):
c = 0
for _ in range(self.n):
x = np.random.random()
y = np.random.random()
if x * x + y * y <=1:
c += 1
return 4*c/self.n
m = Monte(100)
print(m.calc_pi())
# or
m = Monte(n=1000)
m.n
print(m.calc_pi())
Julia
struct Monte
n::Int # field
end
function calc_pi(m::Monte)
c = 0
for _ in 1:m.n
x = rand()
y = rand()
if x^2 + y^2 <= 1
c += 1
end
end
return 4c / m.n
end
m = Monte(1000)
m.n # 1000
pi_approx = calc_pi(m)
@show pi_approx
両者のコードを比べると、
-
関数の引数に入るデータは、pythonでは
__init__
で定義されるが、juliaでは、structで定義されている。 -
pythonのclassで定義されているメソッドcalc_pi(self)が、juliaではcalc_pi関数に対応する。
-
calc_pi関数の引数には、structで定義されたデータ構造が代入されており、これがselfになっている。
まとめ
classとstructの両者の違いを具体的な例を通して確認しつつ、pythonコードからjuliaコードに移植する知見を得た。
まとめると、
まず、pythonコードを見比べて、classの__init__
で定義されたデータをstructで定義する。次に、juliaではメソッドに対応するものとして関数を定義し、その第一引数にstructを代入することで、メソッドのようなものを作ることができる。
参考
pythonからjuliaに移行する際の心理的障壁をなくすための有益な知見が以下にまとめてある。
OOPMacro.jlの話