Ето едно примерно решение - има много вариации, това е просто един
пример.
class Quaternion:
def __init__(self, *args):
if len(args) == 1 and not isinstance(args[0], (int, float)):
self.__init__(*args[0])
elif len(args) == 2:
self.__coordinates = (args[0].real, args[0].imag, args[1].real, args[1].imag)
else:
self.__coordinates = tuple(args + (0, 0, 0, 0))[:4]
def tuple(self):
return self.__coordinates
def __getitem__(self, index):
return self.__coordinates[index]
def __setitem__(self, index):
raise TypeError
def __getattribute__(self, attr):
attrs = ['e', 'i', 'j', 'k']
if attr in attrs: return self[attrs.index(attr)]
if attr == 'scalar': return self[0]
if attr == 'vector': return Quaternion(0, *self[1:])
return object.__getattribute__(self, attr)
def __setattr__(self, attr, value):
if attr in ['e', 'i', 'j', 'k', 'scalar', 'vector']: raise TypeError
return object.__setattr__(self, attr, value)
def __eq__(self, other):
return tuple(self) == tuple(Quaternion(other))
def __add__(self, other):
return Quaternion(*map(sum, zip(self, Quaternion(other))))
__radd__ = __add__
def __neg__(self):
return self * -1
def __sub__(self, other):
return self + (-other)
def __rsub__(self, other):
return (-self) + other
def __mul__(self, other):
q1, q2 = self, Quaternion(other)
return Quaternion(q1.e*q2.e - q1.i*q2.i - q1.j*q2.j - q1.k*q2.k,
q1.e*q2.i + q1.i*q2.e + q1.j*q2.k - q1.k*q2.j,
q1.e*q2.j - q1.i*q2.k + q1.j*q2.e + q1.k*q2.i,
q1.e*q2.k + q1.i*q2.j - q1.j*q2.i + q1.k*q2.e)
__rmul__ = __mul__
def __truediv__(self, other):
return self * (1/other)
def __invert__(self):
return self.scalar - self.vector
def __abs__(self):
return (self * ~self).e ** 0.5
def unit(self):
return self / abs(self)
def reciprocal(self):
return ~self / (abs(self) ** 2)
def __pow__(self, other):
if other == 1: return self
return self ** (other - 1) * self
def __hash__(self):
return hash(tuple(self))
def __bool__(self):
return self != Quaternion()
def __str__(self):
return '{0}{1:+}i{2:+}j{3:+}k'.format(*self)
def __repr__(self):
return 'Quaternion{0}'.format(tuple(self))
Quaternion.e = Quaternion(1, 0, 0, 0)
Quaternion.i = Quaternion(0, 1, 0, 0)
Quaternion.j = Quaternion(0, 0, 1, 0)
Quaternion.k = Quaternion(0, 0, 0, 1)
Заб. вместо
for attr, val in zip('eijk', self): object.__setattr__(self, attr, val) # in __init__ и
scalar = property(lambda self: self.e)
vector = property(lambda self: Quaternion(0, *self[1:]))
може да се откоментира __getattribute__
06.04.2009
(променeно 06.04.2009)