Python中枚举的枚举?
在Python中可以有一个枚举吗?例如,我想Python中枚举的枚举?,python,python-3.x,enums,Python,Python 3.x,Enums,在Python中可以有一个枚举吗?例如,我想 enumA enumB elementA elementB enumC elementC elementD 我可以将elementA称为enumA.enumB.elementA,或者将elementD称为enumA.enumC.elementD 这可能吗?如果是,怎么做 编辑:以朴素的方式实现时: from enum import Enum class EnumA(E
enumA
enumB
elementA
elementB
enumC
elementC
elementD
我可以将elementA
称为enumA.enumB.elementA
,或者将elementD
称为enumA.enumC.elementD
这可能吗?如果是,怎么做
编辑:以朴素的方式实现时:
from enum import Enum
class EnumA(Enum):
class EnumB(Enum):
member = 0
print(EnumA)
print(EnumA.EnumB.member)
它给出:
<enum 'EnumA'>
Traceback (most recent call last):
File "Maps.py", line 15, in <module>
print(EnumA.EnumB.member)
AttributeError: 'EnumA' object has no attribute 'member'
回溯(最近一次呼叫最后一次):
文件“Maps.py”,第15行,在
打印(EnumA.EnumB.member)
AttributeError:'EnumA'对象没有属性'member'
您可以使用namedtuples执行以下操作:
>>> from collections import namedtuple
>>> Foo = namedtuple('Foo', ['bar', 'barz'])
>>> Bar = namedtuple('Bar', ['element_a', 'element_b'])
>>> Barz = namedtuple('Barz', ['element_c', 'element_d'])
>>> bar = Bar('a', 'b')
>>> barz = Barz('c', 'd')
>>> foo = Foo(bar, barz)
>>> foo
Foo(bar=Bar(element_a='a', element_b='b'), barz=Barz(element_c='c', element_d='d'))
>>> foo.bar.element_a
'a'
>>> foo.barz.element_d
'd'
这不是枚举,但可能解决了您的问题您不能使用
enum
stdlib模块来实现这一点。如果您尝试:
class A(Enum):
class B(Enum):
a = 1
b = 2
class C(Enum):
c = 1
d = 2
A.B.a
…您将得到一个异常,如:
AttributeError: 'A' object has no attribute 'a'
这是因为A
的枚举值与A
的实例类似,而与其值类型的实例不同。就像持有int
值的普通枚举在值上没有int
方法一样,B
也不会有enum
方法。比较:
class D(Enum):
a = 1
b = 2
D.a.bit_length()
当然,您可以显式地访问基础值(
int
,或B
类):
D.a.value.bit_length()
A.B.value.a
…但我怀疑这是你想要的
那么,您是否可以使用
IntEnum
使用的相同技巧,对Enum
和int
进行子类化,使其枚举值为int
值,如文档部分所述
不,因为您将子类化什么类型?不枚举
;那已经是你喜欢的类型了。不能使用类型
(任意类的类型)。没有什么是有效的
因此,您必须使用具有不同设计的不同Enum实现来实现这一点。幸运的是,在PyPI和ActiveState上有大约69105个不同的选项可供选择
例如,当我考虑构建类似于Swift枚举(比Python/Java/等枚举更接近ML-adt)的东西时,有人推荐我看一下。我忘了这么做,但现在我只是这么做了,而且:
class A(makeobj.Obj):
class B(makeobj.Obj):
a, b = makeobj.keys(2)
class C(makeobj.Obj):
c, d = makeobj.keys(2)
print(A.B, A.B.b, A.B.b.name, A.B.b.value)
这将为您提供:
<Object: B -> [a:0, b:1]> <Value: B.b = 1> b 1
<enum 'enumA'>
<enum 'enumB'>
enumC.elementD
[a:0,b:1]>b1
如果它查看其创建str/repr值的
\uuuuu qualname\uuuu
而不是\uuuu name\uuuuuuuu
,这可能会很好,但在其他方面,它看起来好像做了您想要的一切。它还有其他一些很酷的功能(不完全是我想要的,但很有趣…。注意,下面的内容很有趣,可能很有用,但正如@abarnert所指出的,生成的A
Enum没有Enum
成员,即list(A)
返回一个空列表
不必评论枚举的枚举是否是一个好主意(我还没有决定;),这可以做到。。。而且只有少量的魔法 您可以从以下位置使用
常量
类:
或者您可以使用新库及其内置的skip
desriptor装饰器(我将展示)
无论如何,通过将子枚举类包装在描述符中,可以避免它们自己成为成员
您的示例如下所示:
from aenum import Enum, skip
class enumA(Enum):
@skip
class enumB(Enum):
elementA = 'a'
elementB = 'b'
@skip
class enumC(Enum):
elementC = 'c'
elementD = 'd'
然后,您可以通过以下方式访问它们:
print(enumA)
print(enumA.enumB)
print(enumA.enumC.elementD)
这给了你:
<Object: B -> [a:0, b:1]> <Value: B.b = 1> b 1
<enum 'enumA'>
<enum 'enumB'>
enumC.elementD
请注意,子枚举在其显示中不包括父枚举;如果这很重要,我建议增强
EnumMeta
以识别常量
描述符,并修改其包含的类“\uuuuu repr\uuuu
”——但我将把它留给读者作为练习 我在基本枚举中创建了一个实现de _uuugetattr uuu的枚举,如下所示
def __getattr__(self, item):
if item != '_value_':
return getattr(self.value, item).value
raise AttributeError
在我的例子中,我有一个enum of enum of enum
class enumBase(Enum):
class innerEnum(Enum):
class innerInnerEnum(Enum):
A
及
基于ATTR的有效解决方案。这还允许实现属性验证器和属性的其他优点:
import enum
import attr
class CoilsTypes(enum.Enum):
heating: str = "heating"
class FansTypes(enum.Enum):
plug: str = "plug"
class HrsTypes(enum.Enum):
plate: str = "plate"
rotory_wheel: str = "rotory wheel"
class FiltersTypes(enum.Enum):
bag: str = "bag"
pleated: str = "pleated"
@attr.dataclass(frozen=True)
class ComponentTypes:
coils: CoilsTypes = CoilsTypes
fans: FansTypes = FansTypes
hrs: HrsTypes = HrsTypes
filter: FiltersTypes = FiltersTypes
cmp = ComponentTypes()
res = cmp.hrs.plate
首先,您必须使用stdlib
enum
模块或第三方模块,以Python语法编写此代码。那么…你试过了吗?发生了什么?我很好奇-为什么您首先需要这个功能?具体的用例是什么?@inspectorG4dget我想在我的RPG引擎的通用对象系统中提供一个对象分类系统。例如,可以将对象分类为terrain.rocks.smallRock或武器、近战、剑、短剑。有更好的方法吗?看起来应该是动态信息,而不是静态信息——换句话说,是存储在字符串或元组中的信息,而不是作为类型的一部分。除非这是为了用于嵌入式Python控制台或其他什么东西?对象引擎中的对象类型是不可变的——尽管我现在正在重新考虑这一点。谢谢。现在这就更有意义了。你建议我怎么做?请参阅我在OP上的评论。@silverwingdseraph:正如我在最后所说的,我将首先查看所有其他enum实现的PyPI和ActiveState,看看其中是否有一个设计更接近您想要的。你所要求的似乎是合理的,只是不是stdlib所采用的设计,所以很有可能其他人也这么做了。谢谢。现在我决定采用一种不同的系统,但我会在某个时候回到这个问题上来,看看那些。事实上,这是可以做到的。请注意,我并不是说这是个好主意。如果你好奇,请检查我的答案。@furman好吧,你的答案实际上没有Enum
值,它有常量
值。当然,您使用的是Enum
类型来定义那些Constant
实例,所以看起来您一直在使用Enum。我认为这可能是误导性的,而不是帮助性的,但答案是值得的——任何读过它并了解它是如何工作的人都会学到一些有用的东西,如果没有其他东西的话。谢谢。虽然这不能解决我的问题,但知道这一点非常有用+这对我来说是最好的答案,因为我有一个巨大的身躯
import enum
import attr
class CoilsTypes(enum.Enum):
heating: str = "heating"
class FansTypes(enum.Enum):
plug: str = "plug"
class HrsTypes(enum.Enum):
plate: str = "plate"
rotory_wheel: str = "rotory wheel"
class FiltersTypes(enum.Enum):
bag: str = "bag"
pleated: str = "pleated"
@attr.dataclass(frozen=True)
class ComponentTypes:
coils: CoilsTypes = CoilsTypes
fans: FansTypes = FansTypes
hrs: HrsTypes = HrsTypes
filter: FiltersTypes = FiltersTypes
cmp = ComponentTypes()
res = cmp.hrs.plate