Python:子类继承了超类属性,但丢失了它的其他属性
所以,我已经编写了一个类来表示向量,称为Vector,我正在尝试编写一个子类,称为Visual_Vector,它包含与向量在屏幕上的显示方式有关的附加属性,例如要绘制的直线的原点和端点。我的问题是,当我创建Visual_vector的实例时,它会丢失self.origin和self.end_point:Python:子类继承了超类属性,但丢失了它的其他属性,python,python-3.x,object,inheritance,subclass,Python,Python 3.x,Object,Inheritance,Subclass,所以,我已经编写了一个类来表示向量,称为Vector,我正在尝试编写一个子类,称为Visual_Vector,它包含与向量在屏幕上的显示方式有关的附加属性,例如要绘制的直线的原点和端点。我的问题是,当我创建Visual_vector的实例时,它会丢失self.origin和self.end_point: >>> a = Visual_vector((0, 0), (45, 330)) >>> a.x 45 >>> a.y 330 >&g
>>> a = Visual_vector((0, 0), (45, 330))
>>> a.x
45
>>> a.y
330
>>> a.length
333.0540496676178
>>> a.origin
>>> a.end_point
我怀疑这可能与我在超类中使用getattr和setattr有关,但除此之外,我不知道问题出在哪里
向量类:
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
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
视觉矢量类:
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
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
由于您观察到的有线行为,您不应该使用这样的_usetattr _;-方法。将其替换为长度或向量属性
您的uuu setattr_uuuu默认拒绝设置除x、y、length或vector之外的任何属性。如果名称不是vector、length或normal,您认为getattr将返回什么?您不应该使用这样的uuu setattr_uuuuuu方法,因为您观察到有线行为。将其替换为长度或向量属性如何获得self.length属性以在每次调用它时计算长度?而且,你们暗示有一种方法可以改变“静默拒绝设置任何其他属性”的行为。如何设置?请注意,由于在定义长度设置器之前已将magnity=length,因此magnity不支持赋值。这与提问者代码的行为相符,但不清楚这是否是双方故意的。这不是我的本意,但谢谢你指出!在某些情况下,uuu setattr_uuu比@property更合适,反之亦然,或者这是一个偏好问题?uu setattr_uuu在设计时不知道属性名称时很有用。