Enum 中的 NumPy 数组值

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

我正在寻找一种为模块声明不可变 numpy 数组的方法。我当前的尝试涉及利用

Enum
类。但是,如果我尝试将 numpy 数组作为值分配给
Enum
类属性,Python 会尝试将不同的值一起广播并引发错误。

这是一个最小的(不)工作示例:

import enum
import numpy as np

class Foo(enum.Enum):
    BAR = np.array([1, 2, 3])
    BAZ = np.array([4, 5])

这会引发错误:

ValueError: operands could not be broadcast together with shapes (3,) (2,)

我注意到使用

lists
而不是
np.arrays
效果很好。同样,我可以将
np.array
包装成
tuple
,但是我对这个解决方案感到不安,因为它感觉有点“不完整”。有没有办法使用 numpy 数组作为
Enum
值?或者也许有更好的方法在模块中声明静态 numpy 数组?

python numpy enums
1个回答
0
投票

对我来说,询问“不可变数组”的问题可以通过两种方式理解:

  1. 是否要确保某个属性一旦分配了初始值就不能再重新分配新值;例如,一旦将数组分配给

    BAR
    ,就不能在那里分配新数组了?

    在这种情况下,使用一些不可变的 Python 数据结构来保存 Numpy 数组,例如元组、命名元组(可以通过两种方式定义,请参阅herehere)或frozen dataclass。然而,这不能确保数组内的值不能被更改。

  2. 您想确保数组内的值无法更改吗?

    在这种情况下,请将阵列上的

    WRITEABLE
    标志 设置为
    False

两种可能性可以按如下方式组合,例如(此处使用冻结数据类来避免属性重新分配,并使用

setflags()
设置数组标志):

from dataclasses import dataclass, FrozenInstanceError
import numpy as np

@dataclass(frozen=True)  # `frozen=True`: disable reassigning to `Foo's` fields
class Foo:
    BAR: np.ndarray
    BAZ: np.ndarray
    
    def __post_init__(self):
        self.BAR.setflags(write=False)  # `write=False`: disable reassigning to
        self.BAZ.setflags(write=False)  #     the entries of the arrays
        
foo = Foo(BAR=np.asarray([1, 2, 3]), BAZ=np.asarray([4, 5]))

try:
    foo.BAR = 42  # Try to assign a new value to `foo.BAR`
except FrozenInstanceError as error:
    print(error)  # >>> cannot assign to field 'BAR'
try:
    foo.BAR[0] = 42  # Try to assign a new value to a value of `foo.BAR`
except ValueError as error:
    print(error)  # >>> assignment destination is read-only

最后一点,请记住冻结数据类的文档所说的内容:不可能创建真正不可变的Python对象。因此,总会有一种方法可以绕过Python中的不变性措施,如果有的话真的尝试这样做。

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