Pythonをはじめてみる(6)

演算子オーバーロード

例えば、「+」をオーバーロードするには、__add__メソッドを定義すればよかった。


class Gal:
def __add__(self, a):
...

a = Gal(-4, -2, 3, 4)
b = Gal(3, -1, 3, 3)
c = a + b

それでは、こんなことをするにはどうすればよいだろう。


a = Gal(-4, -2, 3, 4)
b = a + 1

__add__の第2引数がGalのインスタンスかどうかを判定する。


isinstance(a, Gal)

これでTrueが返ればaはGalのインスタンス。場合分けすればよい。
しかし、こうすると怒られる。


a = Gal(-4, -2, 3, 4)
b = a + 1

こういうときは、__radd__を定義すればよい。


def __radd__(self, a):
return Gal(self.a + a * self.d, self.b, self.c, self.d)

これは__add__だけでできるらしい。


a = Gal(-4, -2, 3, 4)
a += 1

and/or

ブーリアン演算子「&&」「||」の代わりに、「and」「or」を使う。


a = 1
b = a == 1 and a > 0
print b # True



# coding: s_jis

class Gal:
def __init__(self, a, b = 0, c = 0, d = 1):
self.a, self.b, self.c, self.d = a, b, c, d
self.normalize()

def __add__(self, a):
if isinstance(a, Gal):
f = self.GCD(self.d, a.d)
f1 = a.d / f
f2 = self.d / f
return Gal(f1 * self.a + f2 * a.a,
f1 * self.b + f2 * a.b, self.c, f2 * a.d)
else: # 第2引数は整数とみなす
return Gal(self.a + a * self.d, self.b, self.c, self.d)

def __radd__(self, a):
return Gal(self.a + a * self.d, self.b, self.c, self.d)

def normalize(self):
f = self.GCD(self.GCD(self.a, self.b), self.d)
if self.d < 0:
f = -f
self.a /= f
self.b /= f
self.d /= f

def __str__(self):
if self.d == 1:
return self.str_core()
elif self.a == 0 or self.b == 0:
return self.str_core() + "/" + str(self.d)
else:
return "(" + self.str_core() + ")/" + str(self.d)

def str_core(self):
if self.a == 0 and self.b == 0:
result = "0",
else:
result = ""
if self.a != 0:
result = str(self.a)
if self.a != 0 and self.b > 0:
result += "+"
if self.b == 1:
result += "√" + str(self.c)
elif self.b == -1:
result += "-√" + str(self.c)
elif self.b != 0:
result += str(self.b) + "√" + str(self.c)
return result;

def GCD(self, a, b):
if a == 0:
return b
elif b == 0:
return a

a1 = abs(a)
b1 = abs(b)
while True:
a2 = a1 % b1
if a2 == 0:
return b1
b1 %= a1
if b1 == 0:
return a1
a1 = a2

a = Gal(-4, -2, 3, 4)
print a
b = Gal(3, -1, 3, 3)
print b
c = 1 + a
print c
d = Gal(1, 0, 1, 2)
print d
d += 1
print d