enum模块支持枚举的详解(42)Python语言(必读进阶学习教程)(参考资料)
枚举是一组绑定到唯一常量值的符号名称(成员)。在枚举中,可以通过标识来比较成员,并且可以迭代枚举本身。
模块内容
该模块定义了可以用于定义名称和值的独特的套4枚举类:Enum
,IntEnum
,Flag
,和 IntFlag
。它还定义了一个装饰器unique()
和一个辅助器auto
。
- 类
enum.
Enum
- 用于创建枚举常量的基类。有关替代构造语法,请参阅功能API一节 。
- 类
enum.
IntEnum
- 用于创建枚举常量的基类,它们也是子类
int
。
- 类
enum.
IntFlag
- 用于创建枚举常量的基类,可以使用按位运算符进行组合而不会丢失其
IntFlag
成员资格。IntFlag
成员也是子类int
。
- 类
enum.
Flag
- 用于创建枚举常量的基类,可以使用按位运算组合而不会丢失其
Flag
成员资格。
enum.
unique
()- 枚举类装饰器,确保只有一个名称绑定到任何一个值。
- 类
enum.
auto
- 实例将替换为Enum成员的适当值。
新的3.6版:Flag
,IntFlag
,auto
创建枚举
枚举是使用class
语法创建的,这使它们易于读写。Functional API中描述了另一种创建方法 。要定义枚举,子类Enum
如下:
>>> >>> from enum import Enum >>> class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 ...
注意
枚举成员值
成员值可以是任何:int
,str
等等。如果确切的值不重要,您可以使用auto
实例,并为您选择适当的值。如果您auto
与其他值混合,必须小心 。
注意
命名法
- 该类
Color
是枚举(或枚举) - 的属性
Color.RED
,Color.GREEN
等等,都是 枚举成员(或枚举成员)和在功能上是常量。 - 枚举成员具有名称和值(名称为
Color.RED
isRED
,值为Color.BLUE
is3
等)
注意
即使我们使用class
语法来创建枚举,但Enums不是普通的Python类。请参阅Enum如何与众不同?更多细节。
枚举成员具有人类可读的字符串表示形式:
>>> >>> print(Color.RED) Color.RED
……虽然他们repr
有更多的信息:
>>> >>> print(repr(Color.RED)) <Color.RED: 1>
枚举成员的类型是它所属的枚举:
>>> >>> type(Color.RED) <enum 'Color'> >>> isinstance(Color.GREEN, Color) True >>>
枚举成员还有一个只包含其项目名称的属性:
>>> >>> print(Color.RED.name) RED
枚举支持迭代,按定义顺序:
>>> >>> class Shake(Enum): ... VANILLA = 7 ... CHOCOLATE = 4 ... COOKIES = 9 ... MINT = 3 ... >>> for shake in Shake: ... print(shake) ... Shake.VANILLA Shake.CHOCOLATE Shake.COOKIES Shake.MINT
枚举成员是可清除的,因此可以在字典和集合中使用它们:
>>> >>> apples = {} >>> apples[Color.RED] = 'red delicious' >>> apples[Color.GREEN] = 'granny smith' >>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'} True
对枚举成员及其属性的编程访问
有时,以编程方式访问枚举中的成员是有用的(即,Color.RED
由于在程序编写时不知道确切的颜色,因此不会这样做)。 Enum
允许这样的访问:
>>> >>> Color(1) <Color.RED: 1> >>> Color(3) <Color.BLUE: 3>
如果要按名称访问枚举成员,请使用项目访问权限:
>>> >>> Color['RED'] <Color.RED: 1> >>> Color['GREEN'] <Color.GREEN: 2>
如果你有一个枚举成员并需要它name
或value
:
>>> >>> member = Color.RED >>> member.name 'RED' >>> member.value 1
复制枚举成员和值
拥有两个具有相同名称的枚举成员是无效的:
>>> >>> class Shape(Enum): ... SQUARE = 2 ... SQUARE = 3 ... Traceback (most recent call last): ... TypeError: Attempted to reuse key: 'SQUARE'
但是,允许两个枚举成员具有相同的值。给定两个具有相同值的成员A和B(并且A定义为第一个),B是A的别名.A和B的值的值按字母顺序查找将返回A.B的名字查找也将返回A:
>>> >>> class Shape(Enum): ... SQUARE = 2 ... DIAMOND = 1 ... CIRCLE = 3 ... ALIAS_FOR_SQUARE = 2 ... >>> Shape.SQUARE <Shape.SQUARE: 2> >>> Shape.ALIAS_FOR_SQUARE <Shape.SQUARE: 2> >>> Shape(2) <Shape.SQUARE: 2>
注意
尝试创建与已定义属性(另一个成员,方法等)同名的成员或尝试创建与成员同名的属性。
确保唯一的枚举值
默认情况下,枚举允许多个名称作为同一值的别名。如果不需要此行为,可以使用以下装饰器来确保每个值在枚举中只使用一次:
@
enum.
unique
class
专门用于枚举的装饰器。它搜索枚举__members__
收集它找到的任何别名; 如果发现ValueError
有任何细节:
>>> >>> from enum import Enum, unique >>> @unique ... class Mistake(Enum): ... ONE = 1 ... TWO = 2 ... THREE = 3 ... FOUR = 3 ... Traceback (most recent call last): ... ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE
使用自动值
如果确切的值不重要,您可以使用auto
:
>>> >>> from enum import Enum, auto >>> class Color(Enum): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> list(Color) [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
选择的值_generate_next_value_()
可以被覆盖:
>>> >>> class AutoName(Enum): ... def _generate_next_value_(name, start, count, last_values): ... return name ... >>> class Ordinal(AutoName): ... NORTH = auto() ... SOUTH = auto() ... EAST = auto() ... WEST = auto() ... >>> list(Ordinal) [<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]
迭代
迭代枚举的成员不提供别名:
>>> >>> list(Shape) [<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]
特殊属性__members__
是将名称映射到成员的有序字典。它包括枚举中定义的所有名称,包括别名:
>>> >>> for name, member in Shape.__members__.items(): ... name, member ... ('SQUARE', <Shape.SQUARE: 2>) ('DIAMOND', <Shape.DIAMOND: 1>) ('CIRCLE', <Shape.CIRCLE: 3>) ('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)
该__members__
属性可用于对枚举成员进行详细的编程访问。例如,找到所有别名:
>>> >>> [name for name, member in Shape.__members__.items() if member.name != name] ['ALIAS_FOR_SQUARE']
比较
枚举成员按身份进行比较:
>>> >>> Color.RED is Color.RED True >>> Color.RED is Color.BLUE False >>> Color.RED is not Color.BLUE True
不支持枚举值之间的有序比较。枚举成员不是整数(但请参见下面的IntEnum):
>>> >>> Color.RED < Color.BLUE Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: '<' not supported between instances of 'Color' and 'Color'
尽管如此定义了平等比较:
>>> >>> Color.BLUE == Color.RED False >>> Color.BLUE != Color.RED True >>> Color.BLUE == Color.BLUE True
与非枚举值的比较总是比较不相等(同样,IntEnum
明确设计为表现不同,见下文):
>>> >>> Color.BLUE == 2 False
允许的成员和枚举属性
上面的示例使用整数来表示枚举值。使用整数简短而方便(并且由Functional API默认提供),但不严格执行。在绝大多数用例中,人们并不关心枚举的实际价值。但是,如果值很重要,枚举可以具有任意值。
枚举是Python类,可以像往常一样使用方法和特殊方法。如果我们有这个枚举:
>>> >>> class Mood(Enum): ... FUNKY = 1 ... HAPPY = 3 ... ... def describe(self): ... # self is the member here ... return self.name, self.value ... ... def __str__(self): ... return 'my custom str! {0}'.format(self.value) ... ... @classmethod ... def favorite_mood(cls): ... # cls here is the enumeration ... return cls.HAPPY ...
然后:
>>> >>> Mood.favorite_mood() <Mood.HAPPY: 3> >>> Mood.HAPPY.describe() ('HAPPY', 3) >>> str(Mood.FUNKY) 'my custom str! 1'
允许的规则如下:以单个下划线开头和结尾的名称由enum保留,不能使用; 枚举中定义将成为该列举的成员的所有其他属性,具有特殊的方法(例外__str__()
, __add__()
在列出的,等),描述符(方法也描述符),和变量名_ignore_
。
注意:如果您的枚举定义__new__()
和/或__init__()
然后给予枚举成员的任何值将被传递到这些方法中。有关示例,请参阅Planet。
受限制的枚举子类
新Enum
类必须具有一个基本枚举类,最多一个具体数据类型,以及object
根据需要具有多个基础的mixin类。这些基类的顺序是:
def EnumName([mix-in, ...,] [data-type,] base-enum):
pass
此外,仅当枚举未定义任何成员时,才允许子类化枚举。所以这是禁止的:
>>> >>> class MoreColor(Color): ... PINK = 17 ... Traceback (most recent call last): ... TypeError: Cannot extend enumerations
但这是允许的:
>>> >>> class Foo(Enum): ... def some_behavior(self): ... pass ... >>> class Bar(Foo): ... HAPPY = 1 ... SAD = 2 ...
允许对定义成员的枚举进行子类化会导致违反某些类型和实例的重要不变量。另一方面,允许在一组枚举之间共享一些共同行为是有意义的。(有关示例,请参阅OrderedEnum。)
酸洗
可以对枚举进行pickle和unpickled:
>>> >>> from test.test_enum import Fruit >>> from pickle import dumps, loads >>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO)) True
酸洗的通常限制适用:必须在模块的顶层定义可选择的枚举,因为unpickling要求它们可以从该模块导入。
注意
使用pickle协议版本4,可以轻松地挑选嵌套在其他类中的枚举。
可以通过__reduce_ex__()
在枚举类中定义来修改Enum成员的pickle / unpickled方式 。
功能
的Enum
类是可调用,提供以下功能API:
>>> >>> Animal = Enum('Animal', 'ANT BEE CAT DOG') >>> Animal <enum 'Animal'> >>> Animal.ANT <Animal.ANT: 1> >>> Animal.ANT.value 1 >>> list(Animal) [<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
这个API的语义类似于namedtuple
。调用的第一个参数Enum
是枚举的名称。
第二个参数是枚举成员名称的来源。它可以是以空格分隔的名称字符串,名称序列,具有键/值对的2元组序列,或者名称与值的映射(例如字典)。最后两个选项可以为枚举分配任意值; 其他人自动分配从1开始的增加整数(使用start
参数指定不同的起始值)。Enum
返回一个派生的新类。换句话说,上述赋值Animal
相当于:
>>> >>> class Animal(Enum): ... ANT = 1 ... BEE = 2 ... CAT = 3 ... DOG = 4 ...
原因默认为1
为起始号,而不是0
是0
是False
在布尔意义,但枚举成员都执行为True
。
使用功能API创建的酸洗枚举可能很棘手,因为框架堆栈实现细节用于尝试找出创建枚举的模块(例如,如果在单独的模块中使用实用程序函数,它将失败,也可能无法工作在IronPython或Jython上)。解决方案是明确指定模块名称,如下所示:
>>> >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__)
警告
如果module
没有提供,并且Enum无法确定它是什么,则新的Enum成员将不会被取消打击; 为了使错误更接近源,酸洗将被禁用。
在某些情况下,新的泡菜协议4依赖于 __qualname__
设置到泡菜能够找到该类的位置。例如,如果该类在全局范围内的类SomeData中可用:
>>> >>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal')
完整的签名是:
Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)
值: |
新的Enum类将作为其名称记录。 |
---|---|
名称: |
Enum成员。这可以是空格或逗号分隔的字符串(除非另有说明,否则值将从1开始): 'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'
或者名称的迭代器: ['RED', 'GREEN', 'BLUE']
或(名称,值)对的迭代器: [('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]
或映射: {'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
|
模块: |
可以找到新Enum类的模块名称。 |
qualname: |
在模块中可以找到新的Enum类。 |
类型: |
键入以混合到新的Enum类。 |
开始: |
如果只传入名称,则开始计数的数字。 |
在3.5版本中更改:将启动加入参数。
派生枚举
IntEnum
提供的第一个变体Enum
也是它的子类 int
。一个成员IntEnum
可以与整数进行比较; 通过扩展,不同类型的整数枚举也可以相互比较:
>>> >>> from enum import IntEnum >>> class Shape(IntEnum): ... CIRCLE = 1 ... SQUARE = 2 ... >>> class Request(IntEnum): ... POST = 1 ... GET = 2 ... >>> Shape == 1 False >>> Shape.CIRCLE == 1 True >>> Shape.CIRCLE == Request.POST True
但是,它们仍然无法与标准Enum
枚举进行比较:
>>> >>> class Shape(IntEnum): ... CIRCLE = 1 ... SQUARE = 2 ... >>> class Color(Enum): ... RED = 1 ... GREEN = 2 ... >>> Shape.CIRCLE == Color.RED False
IntEnum
值以您期望的其他方式表现为整数:
>>> >>> int(Shape.CIRCLE) 1 >>> ['a', 'b', 'c'][Shape.CIRCLE] 'b' >>> [i for i in range(Shape.SQUARE)] [0, 1]
INTFLAG
下一变化Enum
提供IntFlag
,也是基于int
。IntFlag
可以使用按位运算符(&,|,^,〜)组合成员的差异,结果仍然是 IntFlag
成员。但是,顾名思义,IntFlag
成员也是子类int
,可以在任何地方int
使用。IntFlag
除了逐位操作之外,对成员的任何操作都将失去IntFlag
成员资格。
版本3.6中的新功能。
样本IntFlag
类:
>>> >>> from enum import IntFlag >>> class Perm(IntFlag): ... R = 4 ... W = 2 ... X = 1 ... >>> Perm.R | Perm.W <Perm.R|W: 6> >>> Perm.R + Perm.W 6 >>> RW = Perm.R | Perm.W >>> Perm.R in RW True
也可以命名组合:
>>> >>> class Perm(IntFlag): ... R = 4 ... W = 2 ... X = 1 ... RWX = 7 >>> Perm.RWX <Perm.RWX: 7> >>> ~Perm.RWX <Perm.-8: -8>
IntFlag
和之间的另一个重要区别Enum
是,如果没有设置标志(值为0),它的布尔评估是False
:
>>> >>> Perm.R & Perm.X <Perm.0: 0> >>> bool(Perm.R & Perm.X) False
因为IntFlag
成员也是int
它们的子类,所以它们可以与它们结合使用:
>>> >>> Perm.X | 8 <Perm.8|X: 9>
旗帜
最后一个变种是Flag
。例如IntFlag
,Flag
可以使用按位运算符(&,|,^,〜)组合成员。IntFlag
与之不同 ,它们不能与任何其他Flag
枚举相结合,也不能与之相比int
。虽然可以直接指定值,但建议将其auto
用作值并Flag
选择适当的值。
版本3.6中的新功能。
例如IntFlag
,如果Flag
成员组合导致没有设置标志,则布尔评估为False
:
>>> >>> from enum import Flag, auto >>> class Color(Flag): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> Color.RED & Color.GREEN <Color.0: 0> >>> bool(Color.RED & Color.GREEN) False
单个标志的值应为2的幂(1,2,4,8,…),而标志的组合则不会:
>>> >>> class Color(Flag): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... WHITE = RED | BLUE | GREEN ... >>> Color.WHITE <Color.WHITE: 7>
为“无标志设置”条件赋予名称不会更改其布尔值:
>>> >>> class Color(Flag): ... BLACK = 0 ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> Color.BLACK <Color.BLACK: 0> >>> bool(Color.BLACK) False
注意
对于大多数新代码,Enum
并且Flag
强烈建议,因为IntEnum
并且IntFlag
打破了枚举的一些语义承诺(通过与整数相比,因此通过对其他无关枚举的传递性)。 IntEnum
并且IntFlag
只应在有Enum
或 Flag
没有的情况下使用; 例如,当整数常量被枚举替换时,或者与其他系统互操作时。
其他
虽然IntEnum
是enum
模块的一部分,但它可以非常简单地独立实现:
class IntEnum(int, Enum):
pass
这演示了如何定义类似的派生枚举; 例如StrEnum
,混合str
而不是int
。
一些规则:
- 当子类化时
Enum
,混合类型必须Enum
在基本序列中出现在它自身之前 ,如上IntEnum
例所示。 - 虽然
Enum
可以包含任何类型的成员,但是一旦您混合使用其他类型,所有成员必须具有该类型的值,例如int
上面的值。此限制不适用于仅添加方法且不指定其他数据类型(如int
或)的混合str
。 - 当另一数据类型被混合,该
value
属性是不一样的枚举构件本身,虽然它是等效,将比较相等。 - %样式格式: %s和%r分别调用
Enum
类__str__()
和__repr__()
; 其他代码(例如 IntEnum的%i或%h)将枚举成员视为其混合类型。 - 格式化字符串文字,
str.format()
以及format()
将采用混合式的__format__()
。如果是或 希望使用Enum
类,请使用!s或!r格式代码。str()
repr()
有趣的例子
虽然Enum
,IntEnum
,IntFlag
,并Flag
预计将覆盖大部分的使用情况,他们不能涵盖所有。以下是可以直接使用的一些不同类型的枚举的配方,或者作为创建自己的枚举的示例。
省略值
在许多用例中,人们并不关心枚举的实际值是什么。有几种方法可以定义这种类型的简单枚举:
- 使用
auto
值的实例 - 使用实例
object
作为值 - 使用描述性字符串作为值
- 使用元组作为值和自定义
__new__()
用int
值替换元组
使用这些方法中的任何一种都向用户表明这些值并不重要,并且还使用户可以添加,删除或重新排序成员,而无需重新编号其余成员。
无论您选择哪种方法,都应该提供一个repr()
也隐藏(不重要)值的方法:
>>> >>> class NoValue(Enum): ... def __repr__(self): ... return '<%s.%s>' % (self.__class__.__name__, self.name) ...
使用auto
使用auto
看起来像:
>>> >>> class Color(NoValue): ... RED = auto() ... BLUE = auto() ... GREEN = auto() ... >>> Color.GREEN <Color.GREEN>
使用object
使用object
看起来像:
>>> >>> class Color(NoValue): ... RED = object() ... GREEN = object() ... BLUE = object() ... >>> Color.GREEN <Color.GREEN>
使用描述性字符串
使用字符串作为值将如下所示:
>>> >>> class Color(NoValue): ... RED = 'stop' ... GREEN = 'go' ... BLUE = 'too fast!' ... >>> Color.GREEN <Color.GREEN> >>> Color.GREEN.value 'go'
使用自定义__new__()
使用自动编号__new__()
看起来像:
>>> >>> class AutoNumber(NoValue): ... def __new__(cls): ... value = len(cls.__members__) + 1 ... obj = object.__new__(cls) ... obj._value_ = value ... return obj ... >>> class Color(AutoNumber): ... RED = () ... GREEN = () ... BLUE = () ... >>> Color.GREEN <Color.GREEN> >>> Color.GREEN.value 2
注意
__new__()
如果定义了该方法,则在创建Enum成员期间使用该方法; 然后将它替换为Enum __new__()
,它在创建类之后用于查找现有成员。
OrderedEnum
有序枚举不基于IntEnum
并保持正常Enum
不变量(例如与其他枚举不可比):
>>> >>> class OrderedEnum(Enum): ... def __ge__(self, other): ... if self.__class__ is other.__class__: ... return self.value >= other.value ... return NotImplemented ... def __gt__(self, other): ... if self.__class__ is other.__class__: ... return self.value > other.value ... return NotImplemented ... def __le__(self, other): ... if self.__class__ is other.__class__: ... return self.value <= other.value ... return NotImplemented ... def __lt__(self, other): ... if self.__class__ is other.__class__: ... return self.value < other.value ... return NotImplemented ... >>> class Grade(OrderedEnum): ... A = 5 ... B = 4 ... C = 3 ... D = 2 ... F = 1 ... >>> Grade.C < Grade.A True
DuplicateFreeEnum
如果找到重复的成员名称而不是创建别名,则会引发错误:
>>> >>> class DuplicateFreeEnum(Enum): ... def __init__(self, *args): ... cls = self.__class__ ... if any(self.value == e.value for e in cls): ... a = self.name ... e = cls(self.value).name ... raise ValueError( ... "aliases not allowed in DuplicateFreeEnum: %r --> %r" ... % (a, e)) ... >>> class Color(DuplicateFreeEnum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 ... GRENE = 2 ... Traceback (most recent call last): ... ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN'
注意
这是继承Enum以添加或更改其他行为以及禁止别名的有用示例。如果唯一需要的更改是禁止别名,则unique()
可以使用装饰器。
星球
如果__new__()
或__init__()
定义了枚举成员的值将传递给这些方法:
>>> >>> class Planet(Enum): ... MERCURY = (3.303e+23, 2.4397e6) ... VENUS = (4.869e+24, 6.0518e6) ... EARTH = (5.976e+24, 6.37814e6) ... MARS = (6.421e+23, 3.3972e6) ... JUPITER = (1.9e+27, 7.1492e7) ... SATURN = (5.688e+26, 6.0268e7) ... URANUS = (8.686e+25, 2.5559e7) ... NEPTUNE = (1.024e+26, 2.4746e7) ... def __init__(self, mass, radius): ... self.mass = mass # in kilograms ... self.radius = radius # in meters ... @property ... def surface_gravity(self): ... # universal gravitational constant (m3 kg-1 s-2) ... G = 6.67300E-11 ... return G * self.mass / (self.radius * self.radius) ... >>> Planet.EARTH.value (5.976e+24, 6378140.0) >>> Planet.EARTH.surface_gravity 9.802652743337129
TIMEPERIOD
显示_ignore_
正在使用的属性的示例:
>>> >>> from datetime import timedelta >>> class Period(timedelta, Enum): ... "different lengths of time" ... _ignore_ = 'Period i' ... Period = vars() ... for i in range(367): ... Period['day_%d' % i] = i ... >>> list(Period)[:2] [<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>] >>> list(Period)[-2:] [<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]
Enum与众不同?
枚举有一个自定义元类,它影响派生的枚举类及其实例(成员)的许多方面。
枚举类
该EnumMeta
元类是负责提供 __contains__()
,__dir__()
,__iter__()
和其他方法,使一个做事有Enum
类于一个典型的类失败,如清单(彩色)或some_enum_var的颜色。 EnumMeta
是负责确保对最终各种其它方法Enum
类是正确的(例如__new__()
,__getnewargs__()
, __str__()
和__repr__()
)。
枚举成员(又名实例)
关于Enum成员最有趣的事情是他们是单身人士。 EnumMeta
在创建Enum
类本身时创建它们,然后放置一个自定义__new__()
,以确保通过仅返回现有成员实例来确保不会实例化新的自定义。
更精细的点
支持的__dunder__
名称
__members__
是OrderedDict
的member_name
:member
项目。它只在课堂上提供。
__new__()
如果指定,则必须创建并返回枚举成员; _value_
适当地设置成员也是一个非常好的主意。一旦创建了所有成员,就不再使用它。
支持的_sunder_
名称
_name_
– 会员姓名_value_
– 会员价值; 可以设置/修改__new__
_missing_
– 未找到值时使用的查找函数; 可能会被覆盖_ignore_
– 作为alist()
或a 的名称列表,str()
不会转换为成员,并将从最终的类中删除_order_
– 在Python 2/3代码中使用以确保成员顺序一致(类属性,在类创建期间删除)_generate_next_value_
-所用的功能性API,并通过auto
获得用于枚举成员一个适当的值; 可能会被覆盖
新的3.6版:_missing_
,_order_
,_generate_next_value_
版本3.7中的新功能: _ignore_
为了帮助保持Python 2 / Python 3代码同步,_order_
可以提供属性。它将根据枚举的实际顺序进行检查,如果两者不匹配则引发错误:
>>> >>> class Color(Enum): ... _order_ = 'RED GREEN BLUE' ... RED = 1 ... BLUE = 3 ... GREEN = 2 ... Traceback (most recent call last): ... TypeError: member order does not match _order_
注意
在Python 2代码中,_order_
属性是必需的,因为定义顺序在被记录之前就丢失了。
Enum
成员类型
Enum
成员是他们Enum
班级的实例,通常作为EnumClass.member
。在某些情况下,它们也可以被访问EnumClass.member.member
,但是你永远不应该这样做,因为查找可能会失败,或者更糟糕的是,返回Enum
你正在寻找的成员之外的东西 (这是为成员使用全大写名称的另一个好理由):
>>> >>> class FieldTypes(Enum): ... name = 0 ... value = 1 ... size = 2 ... >>> FieldTypes.value.size <FieldTypes.size: 2> >>> FieldTypes.size.value 2
版本3.5已更改。
Enum
类和成员的布尔值
Enum
了与非混合成员Enum
类型(如 int
,str
等)是根据评估的混合型的规则; 否则,所有成员评估为True
。要使您自己的Enum的布尔值评估取决于成员的值,请将以下内容添加到您的类中:
def __bool__(self):
return bool(self.value)
Enum
课程总是评估为True
。
Enum
带方法的类
如果你给你的Enum
子类额外的方法,比如 上面的Planet类,那些方法将显示在dir()
成员的一个中,但不会出现在类中:
>>> >>> dir(Planet) ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__'] >>> dir(Planet.EARTH) ['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
结合成员Flag
如果未命名Flag成员的组合,repr()
则将包括所有命名标志和值中的所有已命名标志组合:
>>> >>> class Color(Flag): ... RED = auto() ... GREEN = auto() ... BLUE = auto() ... MAGENTA = RED | BLUE ... YELLOW = RED | GREEN ... CYAN = GREEN | BLUE ... >>> Color(3) # named combination <Color.YELLOW: 3> >>> Color(7) # not named combination <Color.CYAN|MAGENTA|BLUE|YELLOW|GREEN|RED: 7>