所以,我写了一个类来表示名为Vector的向量,我试图编写一个名为Visual_vector的子类,其中包含与向量在屏幕上的显示方式有关的其他属性,例如要绘制的线的原点和端点。我的问题是,当我创建一个Visual_vector实例时,它会丢失self.origin和self.end_point:
>>> a = Visual_vector((0, 0), (45, 330))
>>> a.x
45
>>> a.y
330
>>> a.length
333.0540496676178
>>> a.origin
>>> a.end_point
我怀疑这可能与我在超类中使用 getattr 和 setattr 有关,但除此之外我不知道问题是什么< / p>
Vector class:
class Vector():
"""A class to represent a 2D vector"""
def __init__(self, tup):
self.x = tup[0]
self.y = tup[1]
# retrieving attributes
def __getattr__(self, name):
if name == 'vector':
# returns the vector as a tuple
# (x, y)
return (self.x, self.y)
elif name == 'length' or name == 'magnitude':
# returns the length as a float
# sqrt(x^2 + y^2)
return float( sqrt(self.x**2 + self.y**2) )
elif name == 'normal':
# returns a normalized vector as a tuple
# (x/l, y/l)
if self.length == 0:
return (0, 0)
else:
x = self.x / self.length
y = self.y / self.length
return (x, y)
#return (self.x / self.length, self.y / self.length)
# setting attributes
def __setattr__(self, name, value):
if name == 'x' or name == 'y':
# assign value normally
self.__dict__[name] = value
elif name == 'length':
# |(x, y)| * length
# create a new, normalized vector of the same trajectory
new_vector = Vector(self.normal)
# then multiply it by a scalar to get the desired length
self.x = new_vector.x * value
self.y = new_vector.y * value
elif name == 'vector':
# does the same as setting both x and y at the same time
if len(value) == 2: # must be a list or tuple
self.x = value[0]
self.y = value[1]
# mathematical operations
def __add__(self, other):
# (x1 + x2, y1 + y2)
x = self.x + other.x
y = self.y + other.y
return Vector((x, y))
def __iadd__(self, other):
return self + other
def __sub__(self, other):
# (x1 - x2, y1 - y2)
x = self.x - other.x
y = self.y - other.y
return Vector((x, y))
def __isub__(self, other):
return self - other
Visual_vector类:
class Visual_vector(Vector):
"""A class to represent the vectors shown on screen"""
def __init__(self, origin, end_point):
# qualities relative to a coord system
Vector.__init__(self, end_point)
# qualities relative to the screen
self.origin = origin
self.end_point = end_point
答案 0 :(得分:1)
由于您观察到的有线行为,您不应该使用此类__setattr__
- 方法。将其替换为length
- 或vector
- 属性
class Vector(object):
"""A class to represent a 2D vector"""
def __init__(self, tup):
self.x = tup[0]
self.y = tup[1]
# retrieving attributes
@property
def vector(self):
# returns the vector as a tuple
# (x, y)
return (self.x, self.y)
@vector.setter
def vector(self, value):
self.x = value[0]
self.y = value[1]
@property
def length(self):
# returns the length as a float
# sqrt(x^2 + y^2)
return float( sqrt(self.x**2 + self.y**2) )
magnitude = length
@length.setter
def length(self, value):
# |(x, y)| * length
# create a new, normalized vector of the same trajectory
x, y = self.normal
# then multiply it by a scalar to get the desired length
self.x = x * value
self.y = y * value
@property
def normal(self):
# returns a normalized vector as a tuple
# (x/l, y/l)
len = self.length
if len == 0:
return (0, 0)
else:
x = self.x / len
y = self.y / len
return (x, y)
# mathematical operations
def __add__(self, other):
# (x1 + x2, y1 + y2)
x = self.x + other.x
y = self.y + other.y
return Vector((x, y))
def __iadd__(self, other):
self.x += other.x
self.y += other.y
return self
def __sub__(self, other):
# (x1 - x2, y1 - y2)
x = self.x - other.x
y = self.y - other.y
return Vector((x, y))
def __isub__(self, other):
self.x -= other.x
self.y -= other.y
return self
class Visual_vector(Vector):
"""A class to represent the vectors shown on screen"""
def __init__(self, origin, end_point):
# qualities relative to a coord system
Vector.__init__(self, end_point)
# qualities relative to the screen
self.origin = origin
self.end_point = end_point