enum模块定义了:python
Flag, IntFlag, auto在python3.6中加入app
from enum import Enum class Color(Enum): RED = 2 GREEN = 4 BLUE = 6
注意点:
1. 枚举值能够是任何类型,若是值不重要可使用auto()自动选择。但在有其余已定义的值的状况下,谨慎与auto混用
2. Color是枚举类,Color.RED等是枚举成员,枚举成员拥有name和value属性
3. 虽然使用class关键字建立,但枚举并非常规意义上的python类spa
枚举成员的展示形式:3d
>>>print(Color.RED) Color.RED >>>print(repr(Color.RED)) <Color.RED: 2>
枚举成员的type类型是其所属的枚举类:code
>>>type(Color.RED) <enum 'Color'> >>>isinstance(Color.RED, Color) True
枚举支持按照定义时的顺序进行迭代:orm
>>>for color in Color: ... print(color) ... Color.RED Color.GREEN Color.BLUE
枚举成员是可哈希的,所以能够在字典和集合中使用:blog
>>> apples = {} >>> apples[Color.RED] = 'red delicious' >>> apples[Color.GREEN] = 'granny smith' >>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'} True
经过值访问枚举成员:继承
>>>Color(2) <Color.RED: 2>
经过名称访问枚举成员:图片
>>>Color["RED"] <Color.RED: 2>
获取枚举成员的名称和值:ci
>>>member = Color.RED >>>member.name "RED" >>>member.value 2
拥有两个相同名称的枚举成员是不容许的:
>>> class Shape(Enum): ... SQUARE = 2 ... SQUARE = 3 ... Traceback (most recent call last): ... TypeError: Attempted to reuse key: 'SQUARE'
不过不一样的枚举成员容许拥有相同的值。后定义的成员是先定义的成员的别名,经过值或名称访问时都将返回先定义的成员:
>>> 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>
注意点:任意两个枚举属性(包括成员、方法等)不容许存在相同的名称
默认状况下,容许多个成员拥有相同的值。使用unique装饰器能够对枚举值进行惟一约束
@enum.unique
: 枚举专用的类装饰器。它在枚举的__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>]
auto生成什么值取决于_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>) >>> [name for name, member in Shape.__members__.items() if member.name != name] ['ALIAS_FOR_SQUARE']
>>> Color.RED is Color.RED True >>> Color.RED == Color.BLUE False >>> 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 == 6 # 与非枚举的值进行等值比较老是返回False False
枚举是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
注意点:若是枚举中定义了__new()__
或者__init__()
方法,赋值给枚举成员的值将被传递到__new()__
或者__init__()
中
自定义枚举类必须继承自一个枚举基类,至多一个具体的数据类型以及0至多个混合类。继承顺序以下:
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 ...
不能这么作的缘由是可能破坏某些重要的不容许改变的值(原话是would lead to a violation of some important invariants of bytes and instances
)。
>>> from a.b import Color >>> from pickle import dumps, loads >>> Color.RED is loads(dumps(Color.RED)) True
通常要求序列化的枚举要定义在模块顶层,由于反序列化要求枚举可以从模块导入。不过在第4版的pickle协议中,已经能够序列化嵌套在类中的枚举
经过在枚举中定义__reduce_ex__()
方法,能够修改枚举成员的序列化/反序列化行为
枚举类是可调用的:
>>> Animal = Enum("Pet", "Tortoise CAT DOG")
完整的API以下:Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)