|
|
|
@ -70,9 +70,9 @@ follows:: |
|
|
|
|
|
|
|
>>> from enum import Enum |
|
|
|
>>> class Color(Enum): |
|
|
|
... red = 1 |
|
|
|
... green = 2 |
|
|
|
... blue = 3 |
|
|
|
... RED = 1 |
|
|
|
... GREEN = 2 |
|
|
|
... BLUE = 3 |
|
|
|
... |
|
|
|
|
|
|
|
.. note:: Enum member values |
|
|
|
@ -85,10 +85,10 @@ follows:: |
|
|
|
.. note:: Nomenclature |
|
|
|
|
|
|
|
- The class :class:`Color` is an *enumeration* (or *enum*) |
|
|
|
- The attributes :attr:`Color.red`, :attr:`Color.green`, etc., are |
|
|
|
*enumeration members* (or *enum members*). |
|
|
|
- The attributes :attr:`Color.RED`, :attr:`Color.GREEN`, etc., are |
|
|
|
*enumeration members* (or *enum members*) and are functionally constants. |
|
|
|
- The enum members have *names* and *values* (the name of |
|
|
|
:attr:`Color.red` is ``red``, the value of :attr:`Color.blue` is |
|
|
|
:attr:`Color.RED` is ``RED``, the value of :attr:`Color.BLUE` is |
|
|
|
``3``, etc.) |
|
|
|
|
|
|
|
.. note:: |
|
|
|
@ -99,49 +99,49 @@ follows:: |
|
|
|
|
|
|
|
Enumeration members have human readable string representations:: |
|
|
|
|
|
|
|
>>> print(Color.red) |
|
|
|
Color.red |
|
|
|
>>> print(Color.RED) |
|
|
|
Color.RED |
|
|
|
|
|
|
|
...while their ``repr`` has more information:: |
|
|
|
|
|
|
|
>>> print(repr(Color.red)) |
|
|
|
<Color.red: 1> |
|
|
|
>>> print(repr(Color.RED)) |
|
|
|
<Color.RED: 1> |
|
|
|
|
|
|
|
The *type* of an enumeration member is the enumeration it belongs to:: |
|
|
|
|
|
|
|
>>> type(Color.red) |
|
|
|
>>> type(Color.RED) |
|
|
|
<enum 'Color'> |
|
|
|
>>> isinstance(Color.green, Color) |
|
|
|
>>> isinstance(Color.GREEN, Color) |
|
|
|
True |
|
|
|
>>> |
|
|
|
|
|
|
|
Enum members also have a property that contains just their item name:: |
|
|
|
|
|
|
|
>>> print(Color.red.name) |
|
|
|
red |
|
|
|
>>> print(Color.RED.name) |
|
|
|
RED |
|
|
|
|
|
|
|
Enumerations support iteration, in definition order:: |
|
|
|
|
|
|
|
>>> class Shake(Enum): |
|
|
|
... vanilla = 7 |
|
|
|
... chocolate = 4 |
|
|
|
... cookies = 9 |
|
|
|
... mint = 3 |
|
|
|
... VANILLA = 7 |
|
|
|
... CHOCOLATE = 4 |
|
|
|
... COOKIES = 9 |
|
|
|
... MINT = 3 |
|
|
|
... |
|
|
|
>>> for shake in Shake: |
|
|
|
... print(shake) |
|
|
|
... |
|
|
|
Shake.vanilla |
|
|
|
Shake.chocolate |
|
|
|
Shake.cookies |
|
|
|
Shake.mint |
|
|
|
Shake.VANILLA |
|
|
|
Shake.CHOCOLATE |
|
|
|
Shake.COOKIES |
|
|
|
Shake.MINT |
|
|
|
|
|
|
|
Enumeration members are hashable, so they can be used in dictionaries and sets:: |
|
|
|
|
|
|
|
>>> apples = {} |
|
|
|
>>> apples[Color.red] = 'red delicious' |
|
|
|
>>> apples[Color.green] = 'granny smith' |
|
|
|
>>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'} |
|
|
|
>>> apples[Color.RED] = 'red delicious' |
|
|
|
>>> apples[Color.GREEN] = 'granny smith' |
|
|
|
>>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'} |
|
|
|
True |
|
|
|
|
|
|
|
|
|
|
|
@ -149,26 +149,26 @@ Programmatic access to enumeration members and their attributes |
|
|
|
--------------------------------------------------------------- |
|
|
|
|
|
|
|
Sometimes it's useful to access members in enumerations programmatically (i.e. |
|
|
|
situations where ``Color.red`` won't do because the exact color is not known |
|
|
|
situations where ``Color.RED`` won't do because the exact color is not known |
|
|
|
at program-writing time). ``Enum`` allows such access:: |
|
|
|
|
|
|
|
>>> Color(1) |
|
|
|
<Color.red: 1> |
|
|
|
<Color.RED: 1> |
|
|
|
>>> Color(3) |
|
|
|
<Color.blue: 3> |
|
|
|
<Color.BLUE: 3> |
|
|
|
|
|
|
|
If you want to access enum members by *name*, use item access:: |
|
|
|
|
|
|
|
>>> Color['red'] |
|
|
|
<Color.red: 1> |
|
|
|
>>> Color['green'] |
|
|
|
<Color.green: 2> |
|
|
|
>>> Color['RED'] |
|
|
|
<Color.RED: 1> |
|
|
|
>>> Color['GREEN'] |
|
|
|
<Color.GREEN: 2> |
|
|
|
|
|
|
|
If you have an enum member and need its :attr:`name` or :attr:`value`:: |
|
|
|
|
|
|
|
>>> member = Color.red |
|
|
|
>>> member = Color.RED |
|
|
|
>>> member.name |
|
|
|
'red' |
|
|
|
'RED' |
|
|
|
>>> member.value |
|
|
|
1 |
|
|
|
|
|
|
|
@ -179,12 +179,12 @@ Duplicating enum members and values |
|
|
|
Having two enum members with the same name is invalid:: |
|
|
|
|
|
|
|
>>> class Shape(Enum): |
|
|
|
... square = 2 |
|
|
|
... square = 3 |
|
|
|
... SQUARE = 2 |
|
|
|
... SQUARE = 3 |
|
|
|
... |
|
|
|
Traceback (most recent call last): |
|
|
|
... |
|
|
|
TypeError: Attempted to reuse key: 'square' |
|
|
|
TypeError: Attempted to reuse key: 'SQUARE' |
|
|
|
|
|
|
|
However, two enum members are allowed to have the same value. Given two members |
|
|
|
A and B with the same value (and A defined first), B is an alias to A. By-value |
|
|
|
@ -192,17 +192,17 @@ lookup of the value of A and B will return A. By-name lookup of B will also |
|
|
|
return A:: |
|
|
|
|
|
|
|
>>> class Shape(Enum): |
|
|
|
... square = 2 |
|
|
|
... diamond = 1 |
|
|
|
... circle = 3 |
|
|
|
... alias_for_square = 2 |
|
|
|
... SQUARE = 2 |
|
|
|
... DIAMOND = 1 |
|
|
|
... CIRCLE = 3 |
|
|
|
... ALIAS_FOR_SQUARE = 2 |
|
|
|
... |
|
|
|
>>> Shape.square |
|
|
|
<Shape.square: 2> |
|
|
|
>>> Shape.alias_for_square |
|
|
|
<Shape.square: 2> |
|
|
|
>>> Shape.SQUARE |
|
|
|
<Shape.SQUARE: 2> |
|
|
|
>>> Shape.ALIAS_FOR_SQUARE |
|
|
|
<Shape.SQUARE: 2> |
|
|
|
>>> Shape(2) |
|
|
|
<Shape.square: 2> |
|
|
|
<Shape.SQUARE: 2> |
|
|
|
|
|
|
|
.. note:: |
|
|
|
|
|
|
|
@ -227,14 +227,14 @@ found :exc:`ValueError` is raised with the details:: |
|
|
|
>>> from enum import Enum, unique |
|
|
|
>>> @unique |
|
|
|
... class Mistake(Enum): |
|
|
|
... one = 1 |
|
|
|
... two = 2 |
|
|
|
... three = 3 |
|
|
|
... four = 3 |
|
|
|
... ONE = 1 |
|
|
|
... TWO = 2 |
|
|
|
... THREE = 3 |
|
|
|
... FOUR = 3 |
|
|
|
... |
|
|
|
Traceback (most recent call last): |
|
|
|
... |
|
|
|
ValueError: duplicate values found in <enum 'Mistake'>: four -> three |
|
|
|
ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE |
|
|
|
|
|
|
|
|
|
|
|
Using automatic values |
|
|
|
@ -244,12 +244,12 @@ If the exact value is unimportant you can use :class:`auto`:: |
|
|
|
|
|
|
|
>>> from enum import Enum, auto |
|
|
|
>>> class Color(Enum): |
|
|
|
... red = auto() |
|
|
|
... blue = auto() |
|
|
|
... green = auto() |
|
|
|
... RED = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... |
|
|
|
>>> list(Color) |
|
|
|
[<Color.red: 1>, <Color.blue: 2>, <Color.green: 3>] |
|
|
|
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>] |
|
|
|
|
|
|
|
The values are chosen by :func:`_generate_next_value_`, which can be |
|
|
|
overridden:: |
|
|
|
@ -259,13 +259,13 @@ overridden:: |
|
|
|
... return name |
|
|
|
... |
|
|
|
>>> class Ordinal(AutoName): |
|
|
|
... north = auto() |
|
|
|
... south = auto() |
|
|
|
... east = auto() |
|
|
|
... west = auto() |
|
|
|
... NORTH = auto() |
|
|
|
... SOUTH = auto() |
|
|
|
... EAST = auto() |
|
|
|
... WEST = auto() |
|
|
|
... |
|
|
|
>>> list(Ordinal) |
|
|
|
[<Ordinal.north: 'north'>, <Ordinal.south: 'south'>, <Ordinal.east: 'east'>, <Ordinal.west: 'west'>] |
|
|
|
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>] |
|
|
|
|
|
|
|
.. note:: |
|
|
|
|
|
|
|
@ -279,7 +279,7 @@ Iteration |
|
|
|
Iterating over the members of an enum does not provide the aliases:: |
|
|
|
|
|
|
|
>>> list(Shape) |
|
|
|
[<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>] |
|
|
|
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>] |
|
|
|
|
|
|
|
The special attribute ``__members__`` is an ordered dictionary mapping names |
|
|
|
to members. It includes all names defined in the enumeration, including the |
|
|
|
@ -288,16 +288,16 @@ aliases:: |
|
|
|
>>> 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>) |
|
|
|
('SQUARE', <Shape.SQUARE: 2>) |
|
|
|
('DIAMOND', <Shape.DIAMOND: 1>) |
|
|
|
('CIRCLE', <Shape.CIRCLE: 3>) |
|
|
|
('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>) |
|
|
|
|
|
|
|
The ``__members__`` attribute can be used for detailed programmatic access to |
|
|
|
the enumeration members. For example, finding all the aliases:: |
|
|
|
|
|
|
|
>>> [name for name, member in Shape.__members__.items() if member.name != name] |
|
|
|
['alias_for_square'] |
|
|
|
['ALIAS_FOR_SQUARE'] |
|
|
|
|
|
|
|
|
|
|
|
Comparisons |
|
|
|
@ -305,35 +305,35 @@ Comparisons |
|
|
|
|
|
|
|
Enumeration members are compared by identity:: |
|
|
|
|
|
|
|
>>> Color.red is Color.red |
|
|
|
>>> Color.RED is Color.RED |
|
|
|
True |
|
|
|
>>> Color.red is Color.blue |
|
|
|
>>> Color.RED is Color.BLUE |
|
|
|
False |
|
|
|
>>> Color.red is not Color.blue |
|
|
|
>>> Color.RED is not Color.BLUE |
|
|
|
True |
|
|
|
|
|
|
|
Ordered comparisons between enumeration values are *not* supported. Enum |
|
|
|
members are not integers (but see `IntEnum`_ below):: |
|
|
|
|
|
|
|
>>> Color.red < Color.blue |
|
|
|
>>> Color.RED < Color.BLUE |
|
|
|
Traceback (most recent call last): |
|
|
|
File "<stdin>", line 1, in <module> |
|
|
|
TypeError: '<' not supported between instances of 'Color' and 'Color' |
|
|
|
|
|
|
|
Equality comparisons are defined though:: |
|
|
|
|
|
|
|
>>> Color.blue == Color.red |
|
|
|
>>> Color.BLUE == Color.RED |
|
|
|
False |
|
|
|
>>> Color.blue != Color.red |
|
|
|
>>> Color.BLUE != Color.RED |
|
|
|
True |
|
|
|
>>> Color.blue == Color.blue |
|
|
|
>>> Color.BLUE == Color.BLUE |
|
|
|
True |
|
|
|
|
|
|
|
Comparisons against non-enumeration values will always compare not equal |
|
|
|
(again, :class:`IntEnum` was explicitly designed to behave differently, see |
|
|
|
below):: |
|
|
|
|
|
|
|
>>> Color.blue == 2 |
|
|
|
>>> Color.BLUE == 2 |
|
|
|
False |
|
|
|
|
|
|
|
|
|
|
|
@ -350,8 +350,8 @@ Enumerations are Python classes, and can have methods and special methods as |
|
|
|
usual. If we have this enumeration:: |
|
|
|
|
|
|
|
>>> class Mood(Enum): |
|
|
|
... funky = 1 |
|
|
|
... happy = 3 |
|
|
|
... FUNKY = 1 |
|
|
|
... HAPPY = 3 |
|
|
|
... |
|
|
|
... def describe(self): |
|
|
|
... # self is the member here |
|
|
|
@ -363,16 +363,16 @@ usual. If we have this enumeration:: |
|
|
|
... @classmethod |
|
|
|
... def favorite_mood(cls): |
|
|
|
... # cls here is the enumeration |
|
|
|
... return cls.happy |
|
|
|
... return cls.HAPPY |
|
|
|
... |
|
|
|
|
|
|
|
Then:: |
|
|
|
|
|
|
|
>>> Mood.favorite_mood() |
|
|
|
<Mood.happy: 3> |
|
|
|
>>> Mood.happy.describe() |
|
|
|
('happy', 3) |
|
|
|
>>> str(Mood.funky) |
|
|
|
<Mood.HAPPY: 3> |
|
|
|
>>> Mood.HAPPY.describe() |
|
|
|
('HAPPY', 3) |
|
|
|
>>> str(Mood.FUNKY) |
|
|
|
'my custom str! 1' |
|
|
|
|
|
|
|
The rules for what is allowed are as follows: names that start and end with |
|
|
|
@ -393,7 +393,7 @@ Subclassing an enumeration is allowed only if the enumeration does not define |
|
|
|
any members. So this is forbidden:: |
|
|
|
|
|
|
|
>>> class MoreColor(Color): |
|
|
|
... pink = 17 |
|
|
|
... PINK = 17 |
|
|
|
... |
|
|
|
Traceback (most recent call last): |
|
|
|
... |
|
|
|
@ -406,8 +406,8 @@ But this is allowed:: |
|
|
|
... pass |
|
|
|
... |
|
|
|
>>> class Bar(Foo): |
|
|
|
... happy = 1 |
|
|
|
... sad = 2 |
|
|
|
... HAPPY = 1 |
|
|
|
... SAD = 2 |
|
|
|
... |
|
|
|
|
|
|
|
Allowing subclassing of enums that define members would lead to a violation of |
|
|
|
@ -423,7 +423,7 @@ Enumerations can be pickled and unpickled:: |
|
|
|
|
|
|
|
>>> from test.test_enum import Fruit |
|
|
|
>>> from pickle import dumps, loads |
|
|
|
>>> Fruit.tomato is loads(dumps(Fruit.tomato)) |
|
|
|
>>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO)) |
|
|
|
True |
|
|
|
|
|
|
|
The usual restrictions for pickling apply: picklable enums must be defined in |
|
|
|
@ -444,15 +444,15 @@ Functional API |
|
|
|
|
|
|
|
The :class:`Enum` class is callable, providing the following functional API:: |
|
|
|
|
|
|
|
>>> Animal = Enum('Animal', 'ant bee cat dog') |
|
|
|
>>> Animal = Enum('Animal', 'ANT BEE CAT DOG') |
|
|
|
>>> Animal |
|
|
|
<enum 'Animal'> |
|
|
|
>>> Animal.ant |
|
|
|
<Animal.ant: 1> |
|
|
|
>>> Animal.ant.value |
|
|
|
>>> Animal.ANT |
|
|
|
<Animal.ANT: 1> |
|
|
|
>>> Animal.ANT.value |
|
|
|
1 |
|
|
|
>>> list(Animal) |
|
|
|
[<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>] |
|
|
|
[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>] |
|
|
|
|
|
|
|
The semantics of this API resemble :class:`~collections.namedtuple`. The first |
|
|
|
argument of the call to :class:`Enum` is the name of the enumeration. |
|
|
|
@ -467,10 +467,10 @@ new class derived from :class:`Enum` is returned. In other words, the above |
|
|
|
assignment to :class:`Animal` is equivalent to:: |
|
|
|
|
|
|
|
>>> class Animal(Enum): |
|
|
|
... ant = 1 |
|
|
|
... bee = 2 |
|
|
|
... cat = 3 |
|
|
|
... dog = 4 |
|
|
|
... ANT = 1 |
|
|
|
... BEE = 2 |
|
|
|
... CAT = 3 |
|
|
|
... DOG = 4 |
|
|
|
... |
|
|
|
|
|
|
|
The reason for defaulting to ``1`` as the starting number and not ``0`` is |
|
|
|
@ -483,7 +483,7 @@ enumeration is being created in (e.g. it will fail if you use a utility |
|
|
|
function in separate module, and also may not work on IronPython or Jython). |
|
|
|
The solution is to specify the module name explicitly as follows:: |
|
|
|
|
|
|
|
>>> Animal = Enum('Animal', 'ant bee cat dog', module=__name__) |
|
|
|
>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__) |
|
|
|
|
|
|
|
.. warning:: |
|
|
|
|
|
|
|
@ -496,7 +496,7 @@ The new pickle protocol 4 also, in some circumstances, relies on |
|
|
|
to find the class. For example, if the class was made available in class |
|
|
|
SomeData in the global scope:: |
|
|
|
|
|
|
|
>>> Animal = Enum('Animal', 'ant bee cat dog', qualname='SomeData.Animal') |
|
|
|
>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal') |
|
|
|
|
|
|
|
The complete signature is:: |
|
|
|
|
|
|
|
@ -507,19 +507,19 @@ The complete signature is:: |
|
|
|
:names: The Enum members. This can be a whitespace or comma separated string |
|
|
|
(values will start at 1 unless otherwise specified):: |
|
|
|
|
|
|
|
'red green blue' | 'red,green,blue' | 'red, green, blue' |
|
|
|
'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE' |
|
|
|
|
|
|
|
or an iterator of names:: |
|
|
|
|
|
|
|
['red', 'green', 'blue'] |
|
|
|
['RED', 'GREEN', 'BLUE'] |
|
|
|
|
|
|
|
or an iterator of (name, value) pairs:: |
|
|
|
|
|
|
|
[('cyan', 4), ('magenta', 5), ('yellow', 6)] |
|
|
|
[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)] |
|
|
|
|
|
|
|
or a mapping:: |
|
|
|
|
|
|
|
{'chartreuse': 7, 'sea_green': 11, 'rosemary': 42} |
|
|
|
{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42} |
|
|
|
|
|
|
|
:module: name of module where new Enum class can be found. |
|
|
|
|
|
|
|
@ -546,40 +546,40 @@ to each other:: |
|
|
|
|
|
|
|
>>> from enum import IntEnum |
|
|
|
>>> class Shape(IntEnum): |
|
|
|
... circle = 1 |
|
|
|
... square = 2 |
|
|
|
... CIRCLE = 1 |
|
|
|
... SQUARE = 2 |
|
|
|
... |
|
|
|
>>> class Request(IntEnum): |
|
|
|
... post = 1 |
|
|
|
... get = 2 |
|
|
|
... POST = 1 |
|
|
|
... GET = 2 |
|
|
|
... |
|
|
|
>>> Shape == 1 |
|
|
|
False |
|
|
|
>>> Shape.circle == 1 |
|
|
|
>>> Shape.CIRCLE == 1 |
|
|
|
True |
|
|
|
>>> Shape.circle == Request.post |
|
|
|
>>> Shape.CIRCLE == Request.POST |
|
|
|
True |
|
|
|
|
|
|
|
However, they still can't be compared to standard :class:`Enum` enumerations:: |
|
|
|
|
|
|
|
>>> class Shape(IntEnum): |
|
|
|
... circle = 1 |
|
|
|
... square = 2 |
|
|
|
... CIRCLE = 1 |
|
|
|
... SQUARE = 2 |
|
|
|
... |
|
|
|
>>> class Color(Enum): |
|
|
|
... red = 1 |
|
|
|
... green = 2 |
|
|
|
... RED = 1 |
|
|
|
... GREEN = 2 |
|
|
|
... |
|
|
|
>>> Shape.circle == Color.red |
|
|
|
>>> Shape.CIRCLE == Color.RED |
|
|
|
False |
|
|
|
|
|
|
|
:class:`IntEnum` values behave like integers in other ways you'd expect:: |
|
|
|
|
|
|
|
>>> int(Shape.circle) |
|
|
|
>>> int(Shape.CIRCLE) |
|
|
|
1 |
|
|
|
>>> ['a', 'b', 'c'][Shape.circle] |
|
|
|
>>> ['a', 'b', 'c'][Shape.CIRCLE] |
|
|
|
'b' |
|
|
|
>>> [i for i in range(Shape.square)] |
|
|
|
>>> [i for i in range(Shape.SQUARE)] |
|
|
|
[0, 1] |
|
|
|
|
|
|
|
|
|
|
|
@ -656,39 +656,39 @@ flags being set, the boolean evaluation is :data:`False`:: |
|
|
|
|
|
|
|
>>> from enum import Flag |
|
|
|
>>> class Color(Flag): |
|
|
|
... red = auto() |
|
|
|
... blue = auto() |
|
|
|
... green = auto() |
|
|
|
... RED = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... |
|
|
|
>>> Color.red & Color.green |
|
|
|
>>> Color.RED & Color.GREEN |
|
|
|
<Color.0: 0> |
|
|
|
>>> bool(Color.red & Color.green) |
|
|
|
>>> bool(Color.RED & Color.GREEN) |
|
|
|
False |
|
|
|
|
|
|
|
Individual flags should have values that are powers of two (1, 2, 4, 8, ...), |
|
|
|
while combinations of flags won't:: |
|
|
|
|
|
|
|
>>> class Color(Flag): |
|
|
|
... red = auto() |
|
|
|
... blue = auto() |
|
|
|
... green = auto() |
|
|
|
... white = red | blue | green |
|
|
|
... RED = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... WHITE = RED | BLUE | GREEN |
|
|
|
... |
|
|
|
>>> Color.white |
|
|
|
<Color.white: 7> |
|
|
|
>>> Color.WHITE |
|
|
|
<Color.WHITE: 7> |
|
|
|
|
|
|
|
Giving a name to the "no flags set" condition does not change its boolean |
|
|
|
value:: |
|
|
|
|
|
|
|
>>> class Color(Flag): |
|
|
|
... black = 0 |
|
|
|
... red = auto() |
|
|
|
... blue = auto() |
|
|
|
... green = auto() |
|
|
|
... BLACK = 0 |
|
|
|
... RED = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... |
|
|
|
>>> Color.black |
|
|
|
<Color.black: 0> |
|
|
|
>>> bool(Color.black) |
|
|
|
>>> Color.BLACK |
|
|
|
<Color.BLACK: 0> |
|
|
|
>>> bool(Color.BLACK) |
|
|
|
False |
|
|
|
|
|
|
|
.. note:: |
|
|
|
@ -776,12 +776,12 @@ Using :class:`auto` |
|
|
|
Using :class:`object` would look like:: |
|
|
|
|
|
|
|
>>> class Color(NoValue): |
|
|
|
... red = auto() |
|
|
|
... blue = auto() |
|
|
|
... green = auto() |
|
|
|
... RED = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... |
|
|
|
>>> Color.green |
|
|
|
<Color.green> |
|
|
|
>>> Color.GREEN |
|
|
|
<Color.GREEN> |
|
|
|
|
|
|
|
|
|
|
|
Using :class:`object` |
|
|
|
@ -790,12 +790,12 @@ Using :class:`object` |
|
|
|
Using :class:`object` would look like:: |
|
|
|
|
|
|
|
>>> class Color(NoValue): |
|
|
|
... red = object() |
|
|
|
... green = object() |
|
|
|
... blue = object() |
|
|
|
... RED = object() |
|
|
|
... GREEN = object() |
|
|
|
... BLUE = object() |
|
|
|
... |
|
|
|
>>> Color.green |
|
|
|
<Color.green> |
|
|
|
>>> Color.GREEN |
|
|
|
<Color.GREEN> |
|
|
|
|
|
|
|
|
|
|
|
Using a descriptive string |
|
|
|
@ -804,13 +804,13 @@ Using a descriptive string |
|
|
|
Using a string as the value would look like:: |
|
|
|
|
|
|
|
>>> class Color(NoValue): |
|
|
|
... red = 'stop' |
|
|
|
... green = 'go' |
|
|
|
... blue = 'too fast!' |
|
|
|
... RED = 'stop' |
|
|
|
... GREEN = 'go' |
|
|
|
... BLUE = 'too fast!' |
|
|
|
... |
|
|
|
>>> Color.green |
|
|
|
<Color.green> |
|
|
|
>>> Color.green.value |
|
|
|
>>> Color.GREEN |
|
|
|
<Color.GREEN> |
|
|
|
>>> Color.GREEN.value |
|
|
|
'go' |
|
|
|
|
|
|
|
|
|
|
|
@ -827,13 +827,13 @@ Using an auto-numbering :meth:`__new__` would look like:: |
|
|
|
... return obj |
|
|
|
... |
|
|
|
>>> class Color(AutoNumber): |
|
|
|
... red = () |
|
|
|
... green = () |
|
|
|
... blue = () |
|
|
|
... RED = () |
|
|
|
... GREEN = () |
|
|
|
... BLUE = () |
|
|
|
... |
|
|
|
>>> Color.green |
|
|
|
<Color.green> |
|
|
|
>>> Color.green.value |
|
|
|
>>> Color.GREEN |
|
|
|
<Color.GREEN> |
|
|
|
>>> Color.GREEN.value |
|
|
|
2 |
|
|
|
|
|
|
|
|
|
|
|
@ -897,14 +897,14 @@ alias:: |
|
|
|
... % (a, e)) |
|
|
|
... |
|
|
|
>>> class Color(DuplicateFreeEnum): |
|
|
|
... red = 1 |
|
|
|
... green = 2 |
|
|
|
... blue = 3 |
|
|
|
... grene = 2 |
|
|
|
... RED = 1 |
|
|
|
... GREEN = 2 |
|
|
|
... BLUE = 3 |
|
|
|
... GRENE = 2 |
|
|
|
... |
|
|
|
Traceback (most recent call last): |
|
|
|
... |
|
|
|
ValueError: aliases not allowed in DuplicateFreeEnum: 'grene' --> 'green' |
|
|
|
ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN' |
|
|
|
|
|
|
|
.. note:: |
|
|
|
|
|
|
|
@ -1007,10 +1007,10 @@ be provided. It will be checked against the actual order of the enumeration |
|
|
|
and raise an error if the two do not match:: |
|
|
|
|
|
|
|
>>> class Color(Enum): |
|
|
|
... _order_ = 'red green blue' |
|
|
|
... red = 1 |
|
|
|
... blue = 3 |
|
|
|
... green = 2 |
|
|
|
... _order_ = 'RED GREEN BLUE' |
|
|
|
... RED = 1 |
|
|
|
... BLUE = 3 |
|
|
|
... GREEN = 2 |
|
|
|
... |
|
|
|
Traceback (most recent call last): |
|
|
|
... |
|
|
|
@ -1028,7 +1028,8 @@ and raise an error if the two do not match:: |
|
|
|
normally accessed as ``EnumClass.member``. Under certain circumstances they |
|
|
|
can also be accessed as ``EnumClass.member.member``, but you should never do |
|
|
|
this as that lookup may fail or, worse, return something besides the |
|
|
|
:class:`Enum` member you are looking for:: |
|
|
|
:class:`Enum` member you are looking for (this is another good reason to use |
|
|
|
all-uppercase names for members):: |
|
|
|
|
|
|
|
>>> class FieldTypes(Enum): |
|
|
|
... name = 0 |
|
|
|
@ -1078,15 +1079,15 @@ If a combination of Flag members is not named, the :func:`repr` will include |
|
|
|
all named flags and all named combinations of flags that are in the value:: |
|
|
|
|
|
|
|
>>> class Color(Flag): |
|
|
|
... red = auto() |
|
|
|
... green = auto() |
|
|
|
... blue = auto() |
|
|
|
... magenta = red | blue |
|
|
|
... yellow = red | green |
|
|
|
... cyan = green | blue |
|
|
|
... RED = auto() |
|
|
|
... GREEN = auto() |
|
|
|
... BLUE = auto() |
|
|
|
... MAGENTA = RED | BLUE |
|
|
|
... YELLOW = RED | GREEN |
|
|
|
... CYAN = GREEN | BLUE |
|
|
|
... |
|
|
|
>>> Color(3) # named combination |
|
|
|
<Color.yellow: 3> |
|
|
|
<Color.YELLOW: 3> |
|
|
|
>>> Color(7) # not named combination |
|
|
|
<Color.cyan|magenta|blue|yellow|green|red: 7> |
|
|
|
<Color.CYAN|MAGENTA|BLUE|YELLOW|GREEN|RED: 7> |
|
|
|
|