Python:子类继承超类属性,但丢失了它的其他属性

时间:2017-03-29 17:36:55

标签: 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
>>> 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

1 个答案:

答案 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