Python 调用类中的其他方法时缺少类属性

Python 调用类中的其他方法时缺少类属性,python,class-method,class-attributes,Python,Class Method,Class Attributes,我对这一切都是新手,所以请对我放松点 我写了一个类来计算各种向量结果。有几个方法调用类中的其他方法来构造结果。除了一个特殊的问题外,大多数方法都很有效。当我从另一个方法调用一个方法时,该方法的属性以某种方式被删除或丢失,我得到了错误:AttributeError:“list”对象没有属性“dot_prod”,即使方法“dot_prod”是在类中定义的。我发现解决这个问题的唯一方法是使用原始方法调用的返回结果建立对象的新实例。在我的代码中,我包括了问题代码和注释开关的解决方法,以及上下文中的注释,

我对这一切都是新手,所以请对我放松点

我写了一个类来计算各种向量结果。有几个方法调用类中的其他方法来构造结果。除了一个特殊的问题外,大多数方法都很有效。当我从另一个方法调用一个方法时,该方法的属性以某种方式被删除或丢失,我得到了错误:AttributeError:“list”对象没有属性“dot_prod”,即使方法“dot_prod”是在类中定义的。我发现解决这个问题的唯一方法是使用原始方法调用的返回结果建立对象的新实例。在我的代码中,我包括了问题代码和注释开关的解决方法,以及上下文中的注释,以试图解释问题

from math import sqrt, acos, pi

class Vector:

def __init__(self, coordinates):
    try:
        if not coordinates:
            raise ValueError
        self.coordinates = tuple([x for x in coordinates])
        self.dimension = len(coordinates)

    except ValueError:
        raise ValueError('The coordinates must be nonempty')

    except TypeError:
        raise TypeError('The coordinates must be an iterable')


def scalar_mult(self, c):
    new_coordinates = [c*x for x in self.coordinates]
    return new_coordinates


def magnitude(self):
    coord_squared = [x**2 for x in self.coordinates]
    return sqrt(sum(coord_squared))


def normalize(self):
    try:
        mag = self.magnitude()
        norm = self.scalar_mult(1.0/mag)
        return norm

    except ZeroDivisionError:
        return 'Divide by zero error'


def dot_prod(self, v):
    return sum([x*y for x,y in zip(self.coordinates, v.coordinates)])


def angle(self, v):

## This section below is identical to an instructor example using normalized unit
## vectors but it does not work, error indication is 'dot_prod' not
## valid attribute for list object as verified by print(dir(u1)). Instructor is using v2.7, I'm using v3.6.2.
## Performing the self.normalize and v.normalize calls removes the dot_prod and other methods from the return.
## My solution was to create new instances of Vector class object on  self.normalize and v.normalize as shown below:
##        u1 = self.normalize()    # Non working case
##        u2 = v.normalize()       # Non working case
    u1 = Vector(self.normalize())
    u2 = Vector(v.normalize())

    unit_dotprod = round((u1.dot_prod(u2)), 8)

    print('Unit dot product:', unit_dotprod)

    angle = acos(unit_dotprod)
    return angle

#### Test Code #####

v1 = Vector([-7.579, -7.88])
v2 = Vector([22.737, 23.64])


print('Magnitude v1:', v1.magnitude())
print('Normalized v1:', v1.normalize())
print()

print('Magnitude v2:', v2.magnitude())
print('Normalized v2:', v2.normalize())
print()
print('Dot product:', v1.dot_prod(v2))
print('Angle_rad:', v1.angle(v2))
据我所知,“angleself,v”方法就是问题所在,代码中的注释说明了更多。变量u1和u2有一个注释开关可在两者之间切换,您将看到,在工作案例中,我创建了Vector对象的新实例。我根本不知道原始方法调用中缺少属性的原因是什么。调用u1.dot_produ2时的下一行是跟踪错误显示的地方,“dot_prod”从属性中丢失,通过在非工作情况下执行diru1进行验证


欣赏这里的人们的见解。我不太懂技术术语,希望我能跟上。

您试图通过命令u2=v.normalize将列表而不是向量传递给dot_-prod方法;该方法返回的对象是一个列表。我认为,您的问题是,您假设u2将作为类的属性附加,但您必须调用self作为实现这一点的某个点。有两种正确的方法可以调用方法并将输出作为属性重新附加:

1您可以在类实例化后调用它,如下所示:

    vec = Vector([-7.579, -7.88])
    vec.normal_coords = vec.normalize()
如果您不希望对每个向量实例都这样做,并且不需要在一堆其他方法中使用该属性,那么这种方法效果会更好。由于您需要标准化坐标来查找角度,因此我建议您:

2在下面的长代码实例化过程中作为属性附加,以充分展示其工作原理:

from math import sqrt, acos, pi

class Vector(object):

    def __init__(self, coordinates):
        try:
            if not coordinates:
                raise ValueError
            self.coordinates = tuple([x for x in coordinates])
            self.dimension = len(coordinates)

            # Next line is what you want - and it works, even though
            # it *looks like* you haven't defined normalize() yet :)
            self.normalized = self.normalize()

        except ValueError:
            raise ValueError('The coordinates must be nonempty')

        except TypeError:
            raise TypeError('The coordinates must be an iterable')

   [...]

    def dot_prod(self, v):
        # v is class Vector here and in the angle() method
        return sum([x*y for x,y in zip(self.normalized, v.normalized)])


    def angle(self, v):
        unit_dotprod = round((self.dot_prod(v)), 8)

        print('Unit dot product:', unit_dotprod)
        angle = acos(unit_dotprod)

        return angle

谢谢你的评论。我在.normalize函数调用中将列表更改为元组。所以现在dot_prod方法被传递给tuple而不是list,但问题是u1和u2=v.normalize调用中仍然缺少“dot_prod”属性。您对dot_prod调用所做的更改在代码没有崩溃的情况下起作用,但数学是关闭的,这就是您看到ValueError的原因,因为dot乘积返回了错误的值。v、 “规格化”缩放向量,但不幸的是,对象中仍然缺少“dot_prob”属性。试试diru2。啊,是的,你完全正确-在我匆忙中,我没有注意到你想要将标准化坐标传递给角度的点积。我已经有一段时间没有讨论向量了:简单的回答是,您试图将normalize作为一个方法和一个外部函数来附加,而类实际上并不是这样工作的,尽管您可以在初始化内部调用方法并将答案作为一个属性重新附加,我认为这可能是您真正想要的。当我有更多的答案时,我会更新我的答案time@Bill,请按建议更改缩进-否则问题中的代码无效。关于缩进,在我的IDE中一切正常,但当我将其粘贴到此处时,格式不稳定,因此我唯一能让其在代码块中干净地发布的方法是删除def缩进。在粘贴之前,我按照说明缩进了4个空格,但这并不好。我以为我可以很干净地复制和粘贴,但由于某些原因,它并不干净。如果我在这个过程中遗漏了什么,请告诉我,谢谢。@HFBrowning,谢谢你宝贵的反馈。我做了你建议的编辑,它更接近你所需要的。额外的变化是将dot_prod复制到dot_prod_单元,这是角度功能所需的特殊情况。请参见上面的编辑。