Python使用numpy数组类型附加class属性

Python使用numpy数组类型附加class属性,python,python-3.x,list,Python,Python 3.x,List,我想调用一个class属性并将其附加到列表中。下面是一个简单的脚本: class class_1(): def __init__(self): self.x = np.array([0, 0]) def update(self): self.x += 1 return self.x cl_1 = class_1() a = [] for i in range(3): y = cl_1.update() print

我想调用一个class属性并将其附加到列表中。下面是一个简单的脚本:

class class_1():
    def __init__(self):
        self.x = np.array([0, 0])

    def update(self):
        self.x += 1
        return self.x

cl_1 = class_1()
a = []
for i in range(3):
    y = cl_1.update()
    print(y)
    a.append(y)
print(a)  
# output:
[1 1]
[2 2]
[3 3]
[array([3, 3]), array([3, 3]), array([3, 3])]
但是我希望
[array([1,1])、array([2,2])、array([3,3])]
作为list
a
的最终值。我检查了python编号是否没有问题:

class class_2():
    def __init__(self):
        self.x = 0

    def update(self):
        self.x += 1
        return self.x

cl_2 = class_2()
a = []
for i in range(3):
    y = cl_2.update()
    print(y)
    a.append(y)
print(a)
#output
1
2
3
[1, 2, 3]     

与Python整数不同,numpy数组真正允许就地修改。对于不可变的Python整数,
x+=1
x=x+1
具有相同的结果。在这两种情况下,
x
会反弹到一个新的整数对象

对numpy数组执行
self.x+=1
操作时,不会更改
self.x
指向的引用。不分配新数组,而是增加现有数组的内部缓冲区中的每个元素。请注意,赋值仍然发生,但引用与以前相同

要在此上下文中模拟整数的行为,请显式写出所需的操作:

self.x = self.x + 1
在本例中,
self.x+1
是一个全新的数组,然后可以将其作为整数重新分配给
self.x

对于如何修复代码,您有两种选择:

  • 如果每次都可以创建一个新数组并放弃以前的数组,请更改
    update
    方法,如上所示。在某些方面,这个解决方案是最干净的,因为它最小化了对外部引用的影响。同时,您可能不希望每次都创建一个新副本

  • 如果您想在大多数情况下避免创建不必要的副本(或者至少控制副本的制作时间),请使用。不要执行
    a.append(y)
    ,而是执行以下操作

    a.append(y.copy())
    
    或者,立即制作副本:

    y = cl_2.update().copy()
    
  • TL;DR


    最常见的初学者陷阱之一发生在这里:从对同一可变对象的引用创建列表,然后对该对象进行变异。正如预期的那样,所有引用都将以对象的最后一个值结束。

    这是一个重复,已被询问了一百万次(没有对您的反映,OP),但我似乎找不到一个好的候选锤。基本上,请注意,您总是将引用附加到同一数组。+=的全部意义在于它会就地修改,而不是创建副本。您可以使用
    返回self.x.copy()
    来避免此问题。@DYZ。或者更清楚地说,拼出
    self.x=self.x+1
    @madpysicast就够了。取决于上下文。