先日、 第5回Python文法詳解を詳解する会に参加した。 python-in-depth.connpass.com
Pythonの名前空間とクラスに関する話が続き、最後にメタクラスが登場した。 メタクラスは名前こそ聞いたことがあり、クラスを作るクラスなんだなと思いつつ使ってこなかった。 今回、メタクラスに関する話を聞いて過去に挑戦して断念した、「整数剰余環 メタクラスVer.」に再挑戦してみることにした。
メタクラス側で法となる数を属性として保持できるようにし、クラス定義の際に指定できる、というのを目論んで書いてみた。 なお、大半はPythonで整数剰余環 - 何かを書き留める何かを流用している。
class IntMod(type): @classmethod def __prepare__(metacls, name, bases, **kwags): return super().__prepare__(metacls, name, bases) def __new__(metacls, name, bases, ns, **kwags): return super().__new__(metacls, name, bases, ns) def __init__(cls, name, bases, ns, **kwags): type.__init__(cls, name, bases, ns) cls.modulo = kwags['modulo'] class Mod7(metaclass=IntMod, modulo=7): """ 整数剰余環 >>> Mod7(5) 5 (mod 7) >>> Mod7(3) * Mod7(5) 1 (mod 7) >>> Mod7(5) + Mod7(4) 2 (mod 7) >>> Mod7(2) - Mod7(3) 6 (mod 7) >>> Mod7(0) == Mod7(3) + Mod7(4) True >>> Mod7(0) != (Mod7(3) + Mod7(6)) True >>> Mod7(1) / Mod7(3) 5 (mod 7) >>> Mod7(3) * Mod7(1) 3 (mod 7) >>> str(Mod7(2)) '2' >>> int(Mod7(4)) 4 """ def __init__(self, n): self.n = n % Mod7.modulo def __eq__(self, other): return (self.n == other.n) def __ne__(self, other): return (self.n != other.n) def __neg__(self): return Mod7(Mod7.modulo - self.n) def __add__(self, other): return Mod7(self.n + other.n) def __sub__(self, other): return Mod7(self.n - other.n) def __mul__(self, other): return Mod7(self.n * other.n) def __truediv__(self, other): return self.__mul__(other.inverse()) def __repr__(self): return "{0} (mod {1})".format(self.n, Mod7.modulo) def __str__(self): return str(self.n) def __int__(self): return int(self.n) def __egcd__(self, a, b): x, y, u, v = 0, 1, 1, 0 while a != 0: q, r = (b // a), (b % a) m, n = x - (u * q), y - (v * q) b, a, x, y, u, v = a, r, u, v, m, n gcd = b return gcd, x, y def inverse(self): gcd, x, y = self.__egcd__(self.n, Mod7.modulo) if gcd == 1: return Mod7(x) else: raise RuntimeError("Don't exist modulo inverse value...") if __name__ == "__main__": import doctest doctest.testmod()
うーん、使いづらい。どうしたら使いやすくできるだろうか。