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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (212)

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

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])]作为列表的最终价值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都会反弹到一个新的整数对象。

当你做self.x += 1一个numpy的数组,你就不会改变,参考self.x指向。未分配新数组,而是增加现有数组的内部缓冲区中的每个元素。请注意,仍然会发生分配,但使用与之前相同的引用。

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

self.x = self.x + 1

在这种情况下self.x + 1是一个全新的数组,然后可以将其重新分配self.x为整数。

在修改代码方面,您有两种选择:

  1. 如果您可以每次都创建一个新数组,并丢弃以前的数组,请更改update上面显示的方法。在某些方面,此解决方案是最干净的,因为它最大限度地减少了对外部参考的影响。同时,您可能不希望每次都创建新副本。
  2. 如果您想避免在大多数情况下创建不必要的副本(或者至少可以控制副本的制作时间)而不是a.append(y),做 a.append(y.copy()) 或者,立即制作副本: y = cl_2.update().copy()

TL; DR

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

扫码关注云+社区

领取腾讯云代金券