Неизменяемые типы довольно редки в Python и сторонних расширениях; ОП справедливо заявляет, что «линейной алгебры достаточно для использования, поэтому мне кажется, что я не должен бросать свою собственную», - но все известные мне типы, которые используют линейную алгебру, изменчивы ! Таким образом, поскольку ОП непреклонен в неизменности, то - это ничего для него, кроме маршрута «покатай свой собственный».
Не то, чтобы в этом участвовало столько всего, например, если вам конкретно нужны двумерные векторы:
import math
class ImmutableVector(object):
__slots__ = ('_d',)
def __init__(self, x, y):
object.__setattr__(self, _d, (x, y))
def __setattr__(self, n, v):
raise ValueError("Can't alter instance of %s" % type(self))
@property
def x(self):
return self._d[0]
@property
def y(self):
return self._d[1]
def __eq__(self, other):
return self._d == other._d
def __ne__(self, other):
return self._d != other._d
def __hash__(self):
return hash(self._d)
def __add__(self, other):
return type(self)(self.x+other.x, self.y+other.y)
def __mul__(self, scalar):
return type(self)(self.x*scalar, self.y*scalar)
def __repr__(self):
return '%s(%s, %s)' % (type(self).__name__, self.x, self.y)
def __abs__(self):
return math.hypot(self.x, self.y)
Я «добавил бесплатно» несколько дополнительных функций, таких как .x
и .y
Свойства R / O, хорошее представление строк, удобство использования в наборах или в качестве ключей в словах (почему еще нужно иметь неизменность? -), малый объем памяти, abs(v)
для длины вектора v
- я уверен, что вы можете подумать о других методах и операторах "не будет круто, если", в зависимости от области применения и они будут такими же легкими. Если вам нужны другие измерения, это будет не намного сложнее, хотя немного менее читабельно, поскольку нотация .x
, .y
больше не применяется ;-) (но я бы использовал genexps, а не map
) .