我想调用一个class属性,并将其附加到列表中。这是一个简单的脚本:class class_1(): def __init__(self): self.x = np.array([0, 0]) def update(self): self.x += 1 return self.xcl_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.xcl_2 = class_2()a = []for i in range(3): y = cl_2.update() print(y) a.append(y)print(a)#output123[1, 2, 3]
1 回答
慕田峪4524236
TA贡献1875条经验 获得超5个赞
与Python整数不同,numpy数组实际上允许就地修改。使用不可变的Python整数,x += 1
并x = x + 1
具有相同的结果。在这两种情况下,x
都是反弹到一个新的整数对象。
当你做self.x += 1
一个numpy的数组,你就不会更改引用该self.x
点。没有分配新的数组,而是现有数组的内部缓冲区中的每个元素都增加。请注意,分配仍然会发生,但是引用与以前相同。
要在此上下文中模拟整数的行为,请明确写出所需的操作:
self.x = self.x + 1
在这种情况下self.x + 1
是一个全新的数组,然后可以将其重新分配self.x
为整数。
关于如何修复代码,您有两个选择:
如果可以每次都创建一个新数组并丢弃前一个数组,可以
update
按上述方法更改方法。在某些方面,此解决方案是最干净的,因为它可以最大程度地减少对外部参考的影响。同时,您可能不想每次都创建一个新副本。如果您想在大多数情况下避免创建不必要的副本(或者至少可以控制何时创建副本),请使用@DYZ的建议。代替
a.append(y)
,做a.append(y.copy())
或者,立即复制:
y = cl_2.update().copy()
TL; DR
最常见的初学者陷阱发生在这里:从对同一可变对象的引用创建一个列表,然后对该对象进行突变。如预期的那样,所有引用都将以对象的最后一个值结束。
添加回答
举报
0/150
提交
取消