【发布时间】:2021-03-16 07:50:19
【问题描述】:
docs 声明可以通过将某个类型作为 mixin 添加到枚举类中来创建一个其成员完全属于某种类型的枚举类:
虽然 :class:
IntEnum是 :mod:enum模块的一部分,但它会是 独立实现非常简单::class IntEnum(int, Enum): pass这演示了如何定义相似的派生枚举;为了 例如一个 :class:
StrEnum混入 :class:str而不是 :class:int.一些规则:
- 当子类化 :class:
Enum时,混合类型必须出现在 :class:Enum本身之前的基序列中,如 :class:IntEnum上面的例子。- 虽然 :class:
Enum可以有任何类型的成员,但一旦混合了其他类型,所有成员都必须具有该类型的值, 例如:class:int以上。此限制不适用于 仅添加方法而不指定其他类型的混入。- 当混入另一种数据类型时,:attr:
value属性与枚举成员本身不同,尽管它是等价的并且会比较相等。- %-style格式:
%s和%r分别调用:class:Enum类的:meth:__str__和:meth:__repr__;其他代码(例如 如%i或%hfor IntEnum) 将枚举成员视为其混合 输入。- :ref:
Formatted string literals <f-strings>、:meth:str.format和:func:format将使用混合类型的:meth:__format__
除非 :meth:__str__或 :meth:__format__在 子类,在这种情况下被覆盖的方法或 :class:Enum会用到方法。使用 !s 和 !r 格式代码强制使用 :class:Enum类的 :meth:__str__和 :meth:__repr__方法。
我试图创建一个枚举,其成员是类型(type 类型的对象),但由于 type 是一个特殊的类(它是一个元类而不是一个类),我得到了一堆mro、__new__、__init__ 等的参数不匹配等错误:
import enum
class A: pass
class B: pass
class C(B): pass
class MyTypes(type, enum.Enum):
SPAM = A
EGGS = C
错误示例:
Traceback (most recent call last):
File "<file>", line 10, in <module>
class MyTypes(type, enum.Enum):
File "<file>", line 182, in __new__
dynamic_attributes = {k for c in enum_class.mro()
TypeError: descriptor 'mro' of 'type' object needs an argument
有没有办法做到这一点?
我意识到这可能是一个 XY 问题,所以我将解释我的具体示例。在我正在开发的纸牌游戏中,我有一个Card 类层次结构;每个子类代表不同的卡片类型。但是,游戏中的卡牌类型与Card的子类之间的映射可能不是一对一的;例如,可能有一些中间抽象类用作实现帮助,但不代表实际的卡片类型。
所以我想创建一个包含所有游戏卡类型的枚举,并且我希望成员是实现这些类型的实际具体子类,以便我可以轻松地互操作枚举成员和实际类:想法是访问类属性、实例化它们等,而不必每次都使用.value(因为在某些情况下,我可能不得不使用枚举成员或类本身的东西)。
【问题讨论】:
-
即使事实证明这是可能的,生成的枚举成员的语义也会过于混乱。不同的设计会是更好的主意。
-
在您的示例中,您重复使用密钥
EGGS,这会导致错误。 -
@Anakhand:反之亦然。你可以有
FOO=1和BAR=1,但不能有FOO=1和FOO=2。 -
别名是同一个值的另一个名字,不是两个值的同一个名字
-
啊,你是完全正确的,出于某种原因,我脑子里突然出现了这种情况。我已经更正了这个例子。无论如何,这与问题无关。
标签: python enums python-class