很难改变 NumPy 对象数组的单个元素

问题描述 投票:0回答:1

我想创建我的类的唯一实例的 numpy 数组。

import numpy as np

class cell:
    def __init__(self):
        self.id = 0
        self.color = (255, 255, 255)

world = np.full((3, 4), cell(), dtype=object)

我尝试更改单个单元格的

color
id
,但它改变了所有单元格的参数。

python arrays numpy instance
1个回答
0
投票

为什么所有值都会改变?

这种“奇怪”行为的原因是对象引用。请参阅 “最不惊讶”和可变默认参数,了解 list 对象的类似行为的解释。

当您使用 numpy 创建数值数组(这应该是 numpy 数组中唯一可以使用的数据类型)时,实际发生的情况是所有数字在内存中都有不同的引用。因此,这行代码

world = np.full((3, 4), 42, dtype=object)

将在内存中创建一个包含 12 个不同数字的数组,所有这些数字当前的值为 42。

如果您随后更改单个单元格的值,那么它不会影响数组的其他值,因为它们都是内存中不同的对象。这是一种经典行为,您的代码行也可能会发生这种情况。

但是,有了这行代码

world = np.full((3, 4), cell(), dtype=object)

您仅创建 
Cell

类的一个实例。因此,numpy 数组充满了对同一对象的 12 个引用。请参阅

如何克隆列表,以便它在分配后不会意外更改?
,以更好地了解如何复制与引用一起使用的列表和/或用户定义对象。 您还可以检查

有关复制和深度复制

方法的答案,您可能需要在Cell课程中使用这些方法。

如何正确创造独特的价值观?

如前所述,

numpy 数组似乎不是一个特别适合存储通用对象的结构

(例如 Cell 实例)。请参阅下文,了解在您的用例中使用 numpy 的其他想法。

如果您仍然想使用 numpy,您可以尝试以下语法,它将创建 12 个 

Cell

对象的实例,因此修改其中一个不会影响其他任何一个:

world = np.array([cell() for _ in range(12)]).reshape((3, 4))

将 numpy 与您的数据类型结合使用的其他方法

根据您实际的

Cell

类可能是什么,如果它只有数字数据,如您的示例所示,您可能希望将数据转换为列表,然后填充 numpy 数组以进行快速数字运算,同时转换回来之后去

Cell
上课。
本着这种精神的转换函数可能是

import numpy as np class cell: def __init__(self): self.id = 0 self.color = (255, 255, 255) def cell2list(c): """Return a list with numeric values of the cell.""" return [c.id, *c.color] def list2cell(l): """Return a cell created from numeric values of the list.""" c = cell() c.id = l[0] c.color = tuple(l[1:]) return c # Create an empty world array numeric_dimension_of_cell_class = 4 world = np.zeros((3, 4, numeric_dimension_of_cell_class), dtype=object) # Convert cells to numpy world[..., :] = cell2list(cell()) # TODO: Some numeric operations about your cells world[..., 2:] = 0 # e.g. Keep only Red value # Convert back numpy to cells cells = [list2cell(l) for l in world.reshape(-1, numeric_dimension_of_cell_class)]

© www.soinside.com 2019 - 2024. All rights reserved.