我想创建我的类的唯一实例的 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
,但它改变了所有单元格的参数。
为什么所有值都会改变?
这种“奇怪”行为的原因是对象引用。请参阅 “最不惊讶”和可变默认参数,了解 list
对象的类似行为的解释。
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 的其他想法。
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)]