python - 如何返回类实例的副本?

标签 python

我目前正在代码大战中练习python,这里有一个提示:

创建一个支持加法、减法、点积和范数的Vector对象。因此,例如:

    a = Vector([1, 2, 3])
    b = Vector([3, 4, 5])
    c = Vector([5, 6, 7, 8])

    a.add(b)      # should return a new Vector([4, 6, 8])
    a.subtract(b) # should return a new Vector([-2, -2, -2])
    a.dot(b)      # should return 1*3 + 2*4 + 3*5 = 26
    a.norm()      # should return sqrt(1^2 + 2^2 + 3^2) = sqrt(14)
    a.add(c)      # raises an exception

我编写了通过一些测试的加法和减法函数。但是,在运行添加函数后,我遇到了覆盖之前的“a”列表值的问题。当我进行减法时,向量中的“a”值是根据 add 函数的前一个实例计算出的总和。

我怀疑这是因为我运行了这行代码: 返回 self.__class__(self.list) 导致类的实例覆盖自身。

请帮忙,我相信我需要返回该类实例的副本,但不知道该怎么做。

    class Vector:

      def __init__(self, list):

          self.list = list #[1,2]
          self.copylist = list

      def add(self,Vector):

          try:
              self.list = self.copylist

              #take list from other vector
              other = Vector.list

              #take each value from other Vector and add it to self.list
              for index,item in enumerate(Vector.list,0):
                  self.list[index] = item + self.list[index]


          except:
              print("Different size vectors")
          #return the instance of a class
          return self.__class__(self.list)

       def subtract(self,Vector):

          self.list = self.copylist
          other = Vector.list

          print(self.list)
          print(other)

          for index,item in enumerate(Vector.list,0):
              self.list[index] = self.list[index] - item

          return self.__class__(self.list)

       def dot(self,Vector):
          self.list = self.copylist
          other = Vector.list

          #print(self.list)
          #print(other)

          running_sum =0

          for index,item in enumerate(Vector.list,0):
              running_sum = running_sum + item * self.list[index]
              #print(running_sum, " ", self.list[index], " ", item)

          return running_sum

       def norm(self):
          running_sum = 0

          for item in self.list:
              running_sum += item**2

          return running_sum ** 0.5

       def toString(self):
          return str(self.list)

      `def equals(self,Vector):
          return self.list == Vector.list

以下是一些测试:

    a = Vector([1, 2])
    b = Vector([3, 4])

    test.expect(a.add(b).equals(Vector([4, 6])))


    a = Vector([1, 2, 3])
    b = Vector([3, 4, 5])

    test.expect(a.add(b).equals(Vector([4, 6, 8])))
    test.expect(a.subtract(b).equals(Vector([-2, -2, -2]))) #code fails here
    test.assert_equals(a.dot(b), 26)
    test.assert_equals(a.norm(), 14 ** 0.5)

最佳答案

我认为你让事情变得比需要的更复杂。您根本不应该使用类对象。您应该只使用 Vector 类的实例。我认为您的代码应该如下所示:

class Vector:

    def __init__(self, initial_elements):

        self.elements = list(initial_elements) # make a copy of the incoming list of elements

    def add(self, other):

        # insure that the two vectors match in length
        if len(self.elements) != len(other.elements):
            raise Exception("Vector sizes are different")

        # copy our elements
        r = list(self.elements)

        # add the elements from the second vector
        for index, item in enumerate(other.elements, 0):
            r[index] += item

        # return a new vector object defined by the computed elements
        return Vector(r)

    def subtract(self, other):

        # insure that the two vectors match in length
        if len(self.elements) != len(other.elements):
            raise Exception("Vector sizes are different")

        # copy our elements
        r = list(self.elements)

        # subtract the elements from the second vector
        for index, item in enumerate(other.elements, 0):
            r[index] -= item

        # return a new vector object defined by the computed elements
        return Vector(r)

    def dot(self, other):

        running_sum = 0

        for index, item in enumerate(other.elements, 0):
            running_sum += item * self.elements[index]

        return running_sum

    def norm(self):
        running_sum = 0

        for item in self.elements:
            running_sum += item ** 2

        return running_sum ** 0.5

    def toString(self):
        return str(self.elements)

    def equals(self, other):
        return self.elements == other.elements

def test():
    a = Vector([1, 2])
    b = Vector([3, 4])
    print(a.add(b).equals(Vector([4, 6])))

    a = Vector([1, 2, 3])
    b = Vector([3, 4, 5])

    print(a.add(b).equals(Vector([4, 6, 8])))
    print(a.subtract(b).equals(Vector([-2, -2, -2])))
    print(a.dot(b) == 26)
    print(a.norm() == 14 ** 0.5)

test()

结果:

True
True
True
True
True

代码的总体结构是正确的。

需要注意的一件事是,您不应该使用 list 作为变量名称,因为它是 Python 中的类型名称。另外,您不想将 Vector 作为值传递。您希望传递 Vectorlist 的实例,其名称与这些类型名称不冲突。

我的解决方案假设您希望 Vector 实例是不可变的,因此每个操作都将返回一个新的 Vector 对象。您也可以让它们不是不可变的,例如,add 方法只需将传入向量添加到目标向量中,而不创建新对象。我喜欢让它们保持不变。我最近越来越多地进行这种“函数式”编程,其中对对象方法的调用不会修改目标对象(没有副作用),而只是返回一个新对象。

我喜欢您使用 test 类来进行测试。我选择不处理这个问题,只是打印每个测试比较的结果,看看它们是否都为 True。我将让您将测试恢复为使用带有 expectassert_equals 方法的测试对象。<​​/p>

更新:这是编写 addsubtract 方法的更紧凑的方法:

def add(self, other):

    # insure that the two vectors match in length
    if len(self.elements) != len(other.elements):
        raise Exception("Vector sizes are different")

    return Vector([self.elements[i] + other.elements[i] for i in range(len(self.elements))])

def subtract(self, other):

    # insure that the two vectors match in length
    if len(self.elements) != len(other.elements):
        raise Exception("Vector sizes are different")

    return Vector([self.elements[i] - other.elements[i] for i in range(len(self.elements))])

关于python - 如何返回类实例的副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56512465/

相关文章:

python - (Python) 通过单选按钮 python 更新背景

python - 类构造函数可以返回子类吗?

python - 当 "[] == False"成功时,为什么 "if not []"评估为 False?

python - 委托(delegate)与继承python

python - Python 中的重复数据删除

python - 文件操作在相对路径中不起作用

python - 刽子手读取用户的输入文件

python - 在 Anaconda 中运行 matplotlib 时出错

python - `python manage.py shell`启动后执行脚本

python - 列表大小不同