简体   繁体   English

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

[英]Python: subclass inherits super class attributes, but loses it's other attributes

So, I've written a class to represent vectors called Vector, and i'm trying to write a subclass called Visual_vector that contains additional attributes pertaining to how the vector will be displayed on screen, such as the origin and endpoint of the line to be drawn. 因此,我编写了一个表示Vector的类,并且尝试编写一个名为Visual_vector的子类,该子类包含与矢量在屏幕上的显示方式有关的其他属性,例如行的起点和终点。被画下来。 My issue is that when I create an instance of Visual_vector, it loses self.origin and self.end_point: 我的问题是,当我创建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

I suspect this might have something to do with my use of getattr and setattr in the super class, but other than that I have no idea what the issue is 我怀疑这可能与我在超类中使用getattrsetattr有关,但除此之外 ,我不知道问题是什么

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类:

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

You should not use such a __setattr__ -Method because of your observed wired behaviour. 由于观察到的有线行为,您不应使用这种__setattr__ Replace it with a length - or vector -property lengthvector属性替换它

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM