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)