基于 Enum 迭代或索引列表

Iterate or index list based on Enum

我有一个包含 4 个元素的小型枚举列表 (class Type(Enum): One,Two,Three,Four),我想知道是否有办法将枚举与全局列表相关联 (List = [Type(0),Type(1),Type(2),Type(3)]。

我知道我可以使用语法 List[ Type.Two.value ] 访问此列表。但我希望有一个简单的方法来丢失 .value。这不是打字问题——我不介意输入长的描述性变量名。但是列表和枚举直接是 related/associated,所以如果列表将枚举尊重为迭代器,那将是更可取的。有没有简单的方法可以解决这个问题?

我在 Blender 的环境中工作,构建一个附加组件,如果这有什么不同的话。我对 python 也很陌生 - 大约一周了,所以如果你有明显的要点,请不要遗漏。

我对C/C++很熟悉,以防有雷同之处。我非常喜欢创建数据库列表并以一种方式关联迭代器类型,以防止使用与其关联的索引类型名称以外的任何内容访问列表(所以你不会犯像 Cars[my_boat_index] 这样的错误)

感谢任何建议!

您似乎希望通过将索引类型限制为特定类型(例如枚举)来限制对列表的访问。

虽然我不认为这是个好主意,但你绝对可以做到:

from enum import Enum


class MyEnum(Enum):
    ZERO = 0
    ONE = 1
    TWO = 2


class MyList(list):
    def __getitem__(self, item):
        assert isinstance(item, MyEnum)
        return super().__getitem__(item.value)


ml = MyList([1, 2, 3])
print(ml[MyEnum.ONE])
print(ml[1])  # error here

为什么要将对列表的访问限制为与列表索引的默认类型(即 int)不同的类型?

如果您希望拥有特定的属性,为什么不定义一个 class,或者如果您想要通过特定值进行索引,为什么不使用字典?

也许你应该提供一些关于你实际希望做什么的信息 - Python 不是 C/C++,它可能有一些完全有效的方法来做你想做的事情,而不必模仿 C/C++ 的作用。

如果您不想限制,而只是想迭代(这似乎与问题所述不同):

for my_value in MyEnum:
    print(ml[my_value])

如果您不想限制对仅具有该类型的索引的访问,那么您可以省略 assert 语句。

来自文档 https://docs.python.org/3/library/enum.html Enumerations support iteration, in definition order 这样您就可以遍历它们来构建列表,例如:

from enum import Enum

class Numbers(Enum):
    ONE = 1
    TWO = 2
    THREE = 3

assert [Number.value for Number in Numbers]  == [1,2,3]


Enum 转换为列表非常简单:

list(Type)
# [<Type.ONE: 1>, <Type.TWO: 2>, <Type.THREE: 3>, <Type.FOUR: 4>]

使用 Type 个成员作为索引来访问列表有点复杂:

  • 默认情况下,成员值从 1 开始
  • 但容器索引从 0 开始
  • 并且成员没有 __index____int__ 方法

easy/simple 解决方案有两个:

  • 使用IntEnum代替Enum
  • 0
  • 开始计数

所以:

class Type(IntEnum):
    ZERO = 0
    ONE = 1
    TWO = 2
    THREE = 3

IntEnum 成员可以在 int 所在的任何地方使用,因此它们可以很好地用作索引值。

比较复杂的方案是用一个正则Enum,把你需要的方法加进去,返回值的时候减1:

class Type(Enum):
    ONE = 1
    TWO = 2
    THREE = 3
    FOUR = 4

    def __index__(self):
        return self.value - 1

    def __int__(self):
        return self.value - 1

即使您开始添加 __index____int__ 方法,您仍然应该从零开始计数,而不是做减一技巧,因为这会在您以后导致更多问题习惯 Python 的工作方式。