我一直在创建一个几何模块。我已经定义了GeoTuple,Vector(GeoTuple),Normal(Vector)。因为法线必须具有1的大小,所以我需要获取输入参数并在启动Vector之前修改它们,请参阅下面的代码:
class GeoTuple(tuple, object):
def __init__(self, data):
try:
if len(data) != 3:
raise ValueError("Vector must have 3 members only")
_floats = tuple(float(item) for item in data)
super(GeoTuple, self).__init__(_floats)
finally:
pass
def __add__(self, b):
raise NameError("Concatenation has been disabled for GeoTuple")
def __mul__(self, b):
raise NameError("Shallow Copeis has been disabled for GeoTuple")
class Vector(GeoTuple, object):
def __init__(self,point):
super(Vector, self).__init__(point)
@property
def x(self):
return self[0]
@property
def y(self):
return self[1]
@property
def z(self):
return self[2]
@property
def magnitude(self):
_x, _y, _z = self
return sqrt(_x**2 + _y**2 + _z**2)
def __add__(self, b):
_p = (self.x + b.x, self.y + b.y, self.z + b.z)
return Vector(_p)
def __sub__(self, b):
_p = (self.x - b.x, self.y - b.y, self.z - b.z)
return Vector(_p)
def __mul__(self, b):
if isinstance(b, self.__class__):
_s = self.x*b.x + self.y*b.y + self.z*b.z
result = _s
else:
_s = float(b)
_p = (self.x*_s, self.y*_s, self.z*_s)
result = Vector(_p)
return result
def __abs__(self):
return Vector((abs(self.x),abs(self.y),abs(self.z)))
def __neg__(self):
return Vector((-self.x, -self.y, -self.z))
def cross(self, b):
_p = [self.y*b.z - self.z*b.y, self.z*b.x - self.x*b.z,
self.x*b.y - self.y*b.x]
return Vector(_p)
def __xor__(self, b):
return self.cross(b)
class Normal(Vector, object):
def __init__(self, data):
_x, _y, _z = data
_mag = sqrt(_x**2 + _y**2 + _z**2)
_p = [_x/_mag, _y/_mag, _z/_mag]
super(Vector, self).__init__(_p)
问题是,如果我打电话:
n1 = Normal([1,3,8])
n1
它返回:
(1,3,8)
不
(0.11624763874381928, 0.34874291623145787, 0.9299811099505543)
我在正常情况下将参数名称从点更改为数据(这只是一个复制粘贴错误)。 GeoTuple必须保持不变,所以听起来像 new 是实现它的方法吗?你能提供一个具体的例子吗?
答案 0 :(得分:1)
元组是不可变的,因此试图在__init__
中更改它有点晚了。要么覆盖__new__
,要么将基类更改为可变列表。
这有效:
class GeoTuple(list, object): #list not tuple
....
class Normal(Vector, object):
def __init__(self, point):
_x, _y, _z = point #same name as param
_mag = (_x**2 + _y**2 + _z**2)**.5
_p = [_x/_mag, _y/_mag, _z/_mag]
super(Normal, self).__init__(_p) #right class name
n1 = Normal([1,3,8])
print n1
输出是:
[0.11624763874381928, 0.34874291623145787, 0.9299811099505543]
答案 1 :(得分:0)
从普通中移除__init__
并添加__new__
,我就能实现我的目标。
class Normal(Vector, object):
def __new__(self, data):
_x, _y, _z = data
_mag = sqrt(_x**2 + _y**2 + _z**2)
_p = [_x/_mag, _y/_mag, _z/_mag]
return Vector.__new__(self,_p)
答案 2 :(得分:-1)