On this page
枚举—支持枚举
3.4 版的新Function。
源代码: Lib/enum.py
枚举是绑定到唯一,恒定值的一组符号名称(成员)。在枚举中,可以pass身份比较成员,并且可以迭代枚举本身。
Module Contents
该模块定义了四个枚举类,可用于定义唯一的名称和值集:Enum,IntEnum,Flag和IntFlag。它还定义了一个装饰器unique()和一个辅助器auto。
类别
enum.
Enum
- 用于创建枚举常量的 Base Class。有关替代的构造语法,请参见第Functional API节。
类别
enum.
IntEnum
- 用于创建枚举常量的 Base Class,这些常量也是int的子类。
类别
enum.
IntFlag
类别
enum.
Flag
- 用于创建枚举常量的 Base Class,这些常量可以使用按位运算进行组合而不会失去其Flag成员资格。
enum.
unique
( )- 枚举类装饰器,可确保仅将一个名称绑定到任何一个值。
类别
enum.
auto
- 实例将替换为 Enum 成员的适当值。初始值从 1 开始。
3.6 版的新Function:Flag
,IntFlag
,auto
创建枚举
枚举使用class语法创建,这使得它们易于读取和写入。另一种创建方法在Functional API中描述。要定义枚举,请子类Enum如下:
>>> from enum import Enum
>>> class Color(Enum):
... RED = 1
... GREEN = 2
... BLUE = 3
...
Note
Nomenclature
Color
类是枚举(或* enum *)属性
Color.RED
,Color.GREEN
等是枚举成员(或枚举成员),并且是Function常数。枚举成员具有* names 和 values *(
Color.RED
的名称为RED
,Color.BLUE
的值为3
等)。
枚举成员具有人类可读的字符串表示形式:
>>> print(Color.RED)
Color.RED
…虽然他们的repr
拥有更多信息:
>>> print(repr(Color.RED))
<Color.RED: 1>
枚举成员的* type *是它所属的枚举:
>>> type(Color.RED)
<enum 'Color'>
>>> isinstance(Color.GREEN, Color)
True
>>>
枚举成员还具有仅包含其项目名称的属性:
>>> print(Color.RED.name)
RED
枚举支持按定义 Sequences 进行迭代:
>>> 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>
如果要按* name *访问枚举成员,请使用项访问:
>>> 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>
Note
不允许try使用与已经定义的属性相同的名称创建成员(另一个成员,方法等),或者try创建与成员相同名称的属性。
确保唯一的枚举值
默认情况下,枚举允许将多个名称用作同一值的别名。当不需要这种行为时,可以使用以下装饰器来确保每个值在枚举中仅使用一次:
@
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'>]
Note
必须在任何成员之前定义_generate_next_value_()
方法。
Iteration
遍历枚举的成员不提供别名:
>>> list(Shape)
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]
特殊属性__members__
是名称到成员的只读有序 Map。它包括枚举中定义的所有名称,包括别名:
>>> 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']
Comparisons
枚举成员按身份进行比较:
>>> 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
...
Then:
>>> Mood.favorite_mood()
<Mood.HAPPY: 3>
>>> Mood.HAPPY.describe()
('HAPPY', 3)
>>> str(Mood.FUNKY)
'my custom str! 1'
允许的规则如下:以单个下划线开头和结尾的名称被枚举保留,不能使用;枚举中定义的所有其他属性将成为该枚举的成员,但特殊方法(str(),add()等),Descriptors(方法也是 Descriptors)以及在_ignore_
中列出的变量名称除外。
注意:如果您的枚举定义了new()和/或init(),则赋予枚举成员的任何值都将传递到这些方法中。有关示例,请参见Planet。
受限制的枚举子类化
新的Enum类必须具有一个基本的 Enum 类,最多一种具体的数据类型以及所需的基于object的混合类。这些 Base Class 的 Sequences 为:
class 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。)
Pickling
枚举可以腌制和不腌制:
>>> from test.test_enum import Fruit
>>> from pickle import dumps, loads
>>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO))
True
适用于 Pickling 的通常限制:可酸 Eclipse 的枚举必须在模块的顶层定义,因为解酸要求它们可从该模块导入。
Note
使用第 4 版的 pickle 协议,可以轻松地对嵌套在其他类中的枚举进行 pickle。
pass在枚举类中定义reduce_ex(),可以修改如何对 Enum 成员进行 Pickling/Pickling。
Functional API
Enum类是可调用的,提供以下Function性 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的第一个参数是枚举的名称。
第二个参数是枚举成员名称的“来源”。它可以是由空格分隔的名称字符串,名称序列,带有键/值对的 2Tuples 序列或名称到值的 Map(例如字典)。最后两个选项可为枚举分配任意值;其他自动分配以 1 开头的递增整数(使用start
参数指定其他起始值)。返回从Enum派生的新类。换句话说,对Animal
的上述分配等效于:
>>> class Animal(Enum):
... ANT = 1
... BEE = 2
... CAT = 3
... DOG = 4
...
默认为1
作为起始编号而不是0
的原因是0
在布尔意义上是False
,但是枚举成员的所有值均为True
。
使用Function性 API 创建的 Pickling 枚举可能很棘手,因为使用框架堆栈实现详细信息来try找出要在哪个模块中创建枚举(例如,如果您在单独的模块中使用 Util Function,它将失败.在 IronPython 或 Jython 上)。解决方案是显式指定模块名称,如下所示:
>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__)
Warning
如果未提供module
,并且 Enum 无法确定它是什么,新的 Enum 成员将不会被取消;为了使错误更接近源,将禁用 Pickling。
在某些情况下,新的 pickle 协议 4 还依赖于qualname被设置为 pickle 能够找到该类的位置。例如,如果该类在全局范围内的 SomeData 类中可用:
>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal')
完整的签名是:
Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)
value
- 新的 Enum 类将记录为其名称的内容。
names
- 枚举成员。可以是空格或逗号分隔的字符串(除非另有说明,否则值将从 1 开始):
'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'
或名称的迭代器:
['RED', 'GREEN', 'BLUE']
或(名称,值)对的迭代器:
[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]
或 Map:
{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
module
- 可以在其中找到新的 Enum 类的模块的名称。
qualname
- 在模块中可以找到新的 Enum 类的位置。
type
- 键入以混入新的 Enum 类。
start
- 如果仅传入名称,则从该数字开始计数。
在版本 3.5 中更改:添加了* start *参数。
Derived Enumerations
IntEnum
提供的Enum的第一个变体也是int的子类。 IntEnum的成员可以与整数进行比较;pass扩展,还可以将不同类型的整数枚举相互比较:
>>> 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 版的新Function。
samplesIntFlag类:
>>> 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
最后一个变量是Flag。像IntFlag一样,Flag成员可以使用按位运算符(&,|,^,~)进行组合。与IntFlag不同,它们不能与任何其他Flag枚举或int组合或比较。虽然可以直接指定值,但建议使用auto作为值,并让Flag选择适当的值。
3.6 版的新Function。
与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
Note
Others
尽管IntEnum是enum模块的一部分,但独立实现非常简单:
class IntEnum(int, Enum):
pass
这说明了如何定义相似的派生枚举。例如StrEnum
混入str而不是int。
Some rules:
当对Enum进行子类化时,混合类型必须按照基数 Sequences 出现在Enum本身之前,如上面的IntEnum示例所示。
Enum可以具有任何类型的成员,但是一旦您混合使用其他类型,所有成员都必须具有该类型的值,例如上面int。此限制不适用于仅添加方法且未指定int或str之类的其他数据类型的混入。
当混入另一种数据类型时,
value
属性与枚举成员本身不是“相同”,尽管它是等效的并且将比较相等。%样式格式:%s 和%r 分别调用Enum类的str()和repr();其他代码(例如 IntEnum 的%i 或%h)将枚举成员视为其混合类型。
格式化的字符串 Literals,str.format()和format()将使用混合类型的format()。如果需要Enum类的str()或repr(),请使用!s 或!r 格式代码。
何时使用__new __()和__init __()
每当您要自定义Enum成员的实际值时,都必须使用new()。可以使用new()或init()进行其他任何修改,最好使用init()。
例如,如果您要将多个项目传递给构造函数,但只希望其中一个成为值:
>>> class Coordinate(bytes, Enum):
... """
... Coordinate with binary codes that can be indexed by the int code.
... """
... def __new__(cls, value, label, unit):
... obj = bytes.__new__(cls, [value])
... obj._value_ = value
... obj.label = label
... obj.unit = unit
... return obj
... PX = (0, 'P.X', 'km')
... PY = (1, 'P.Y', 'km')
... VX = (2, 'V.X', 'km/s')
... VY = (3, 'V.Y', 'km/s')
...
>>> print(Coordinate['PY'])
Coordinate.PY
>>> print(Coordinate(3))
Coordinate.VY
Interesting examples
虽然Enum,IntEnum,IntFlag和Flag涵盖了大多数用例,但它们不能涵盖所有用例。这里是一些不同类型的枚举的配方,这些枚举可以直接使用,也可以作为创建自己的示例。
Omitting values
在许多用例中,人们并不关心枚举的实际值是多少。有几种定义这种简单枚举类型的方法:
使用这些方法中的任何一种都向用户表明这些值并不重要,并且还使人们能够添加,删除或重新排序成员,而不必重新编号其余成员。
无论选择哪种方法,都应提供一个repr(),该repr()也隐藏(不重要的)值:
>>> class NoValue(Enum):
... def __repr__(self):
... return '<%s.%s>' % (self.__class__.__name__, self.name)
...
Using auto
使用auto看起来像:
>>> class Color(NoValue):
... RED = auto()
... BLUE = auto()
... GREEN = auto()
...
>>> Color.GREEN
<Color.GREEN>
Using 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
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'
Note
这是将 Enum 子类化以添加或更改其他行为以及禁止别名的有用示例。如果唯一需要的更改是禁止使用别名,则可以使用unique()装饰器代替。
Planet
如果定义了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 Classes
EnumMeta
元类负责提供contains(),dir(),iter()和其他方法,这些方法允许一个人处理Enum类,而该类在典型类上失败,例如 color 中的 list(Color)或 some_enum_var。 EnumMeta
负责确保finallyEnum类上的各种其他方法正确(例如new(),getnewargs(),str()和repr())。
枚举成员(又名实例)
关于枚举成员最有趣的事情是他们是 singleton。 EnumMeta
会在创建Enum类本身的同时创建它们的全部,然后放置自定义new(),以确保仅返回现有成员实例就不会实例化任何新实例。
Finer Points
支持的__dunder_名称
__members__
是member_name
:member
个项目的只读有序 Map。仅在类上可用。
new()(如果已指定)必须创建并返回枚举成员;适当设置成员的_value_
也是一个好主意。创建所有成员后,将不再使用它。
支持的_sunder 名称
_name_
–成员名称_value_
–会员的价值;可以在__new__
中设置/修改_missing_
–未找到值时使用的查找Function;可能被覆盖_order_
–在 Python 2/3 代码中使用,以确保成员 Sequences 一致(类属性,在类创建期间删除)_generate_next_value_
–由Functional API和auto用于为枚举成员获取适当的值;可能被覆盖
3.6 版的新Function:_missing_
,_order_
,_generate_next_value_
3.7 版的新Function:_ignore_
为了帮助保持 Python 2/Python 3 代码同步,可以提供_order_
属性。将根据枚举的实际 Sequences 对其进行检查,如果两者不匹配,则会引发错误:
>>> 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_
Note
在 Python 2 代码中,_order_
属性是必需的,因为在记录之前定义 Sequences 会丢失。
枚举成员类型
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类型(例如int,str等)混合的Enum个成员;否则,所有成员的评估结果均为True。要使自己的 Enum 的布尔值评估取决于成员的值,请在类中添加以下内容:
def __bool__(self):
return bool(self.value)
带有方法的枚举类
如果您为Enum子类提供额外的方法,例如上面的Planet类,则这些方法将显示在成员的dir()中,但不在该类的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>