Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:子类继承了超类属性,但丢失了它的其他属性_Python_Python 3.x_Object_Inheritance_Subclass - Fatal编程技术网

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

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

所以,我已经编写了一个类来表示向量,称为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有关,但除此之外,我不知道问题出在哪里

向量类:

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在设计时不知道属性名称时很有用。