Reputation: 515
I have a small enum list of 4 elements (class Type(Enum): One,Two,Three,Four
), and I'm wondering if there is a way to associate the enum with a global list (List = [Type(0),Type(1),Type(2),Type(3)
].
I know I can access this list using the syntax List[ Type.Two.value ]
. But I'm hoping there is a simple way to lose the .value
. It's not a typing problem - I don't mind typing long descriptive variable names. But the list and enum are directly related/associated, so it would be preferable if the list respected the enum as an iterator. Is there a simple way to pull this off?
I'm working in the environment of Blender, building an add-on, if that makes any difference. I'm also very new to python altogether - about a week old, so do not omit obvious points if you have them.
I'm very familiar with C/C++, in case there are any similarities. I was a big fan of creating data library lists and associating iterator types in a way that prevented access to the list using anything other than the index typename associated with it (so you couldn't make a mistake like Cars[my_boat_index]
)
I appreciate any advice!
Upvotes: 2
Views: 4806
Reputation: 69041
Turning an Enum
into a list is as easy as:
list(Type)
# [<Type.ONE: 1>, <Type.TWO: 2>, <Type.THREE: 3>, <Type.FOUR: 4>]
Accessing a list using Type
members as indices is a little more complicated:
__index__
and __int__
methodsThe easy/simple solution is twofold:
IntEnum
instead of Enum
0
So:
class Type(IntEnum):
ZERO = 0
ONE = 1
TWO = 2
THREE = 3
IntEnum
members can be used anywhere an int
is, so they work fine as index values.
The more complicated solution is to use a regular Enum
, add in the methods you need, and subtract 1 when returning the value:
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
Even if you go with adding the __index__
and __int__
methods, you should still just start counting at zero instead of doing the subtract one trick, as that will cause more problems later when you get used to the way Python works.
Upvotes: 3
Reputation: 31319
It appears you're looking to restrict access to a list by restricting the type of the index to a specific type (e.g. an Enum).
Although I don't think it's a good idea, you can definitely do it:
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
Why would you want to restrict access to a list to a different type than the default type for list index (i.e. int
) though?
If you're looking to have specific attributes, why not define a class, or if you want to index through specific values, why not use a dict?
Perhaps you should provide some information on what you're actually hoping to do - Python is not C/C++ and it probably has some perfectly valid way of doing what you want to do, without having to emulate what C/C++ does instead.
If you're not looking to restrict, but just to iterate (which seems to be distinct from what the question stated):
for my_value in MyEnum:
print(ml[my_value])
You could then leave out the assert
statement, if you're not interesting in limiting access to indices with that type only.
Upvotes: 0
Reputation: 965
From the docs https://docs.python.org/3/library/enum.html Enumerations support iteration, in definition order
so you can iterate over them to build lists, for example:
from enum import Enum
class Numbers(Enum):
ONE = 1
TWO = 2
THREE = 3
assert [Number.value for Number in Numbers] == [1,2,3]
Upvotes: 0