blob: c2030faf8bbda704af41eead07c4b0e41581b8c5 [file] [log] [blame]
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001:mod:`enum` --- Support for enumerations
2========================================
3
4.. module:: enum
Brett Cannon15e489f2013-06-14 21:59:16 -04005 :synopsis: Implementation of an enumeration class.
6
Ethan Furman6b3d64a2013-06-14 16:55:46 -07007.. :moduleauthor:: Ethan Furman <ethan@stoneleaf.us>
8.. :sectionauthor:: Barry Warsaw <barry@python.org>,
9.. :sectionauthor:: Eli Bendersky <eliben@gmail.com>,
10.. :sectionauthor:: Ethan Furman <ethan@stoneleaf.us>
11
12**Source code:** :source:`Lib/enum.py`
13
14----------------
15
16An enumeration is a set of symbolic names (members) bound to unique, constant
17values. Within an enumeration, the members can be compared by identity, and
18the enumeration itself can be iterated over.
19
20This module defines two enumeration classes that can be used to define unique
Ethan Furmanf24bb352013-07-18 17:05:39 -070021sets of names and values: :class:`Enum` and :class:`IntEnum`. It also defines
22one decorator, :func:`unique`, that ensures only unique member values are
23present in an enumeration.
24
Ethan Furman6b3d64a2013-06-14 16:55:46 -070025
26Creating an Enum
27----------------
28
29Enumerations are created using the :keyword:`class` syntax, which makes them
30easy to read and write. An alternative creation method is described in
31`Functional API`_. To define an enumeration, subclass :class:`Enum` as
32follows::
33
34 >>> from enum import Enum
35 >>> class Color(Enum):
36 ... red = 1
37 ... green = 2
38 ... blue = 3
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070039 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -070040
Ethan Furman455bfde2013-09-08 23:48:34 -070041.. note:: Nomenclature
42
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070043 - The class :class:`Color` is an *enumeration* (or *enum*)
44 - The attributes :attr:`Color.red`, :attr:`Color.green`, etc., are
45 *enumeration members* (or *enum members*).
46 - The enum members have *names* and *values* (the name of
47 :attr:`Color.red` is ``red``, the value of :attr:`Color.blue` is
48 ``3``, etc.)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070049
Ethan Furman9a1daf52013-09-27 22:58:06 -070050.. note::
51
52 Even though we use the :keyword:`class` syntax to create Enums, Enums
53 are not normal Python classes. See `How are Enums different?`_ for
54 more details.
55
Ethan Furman6b3d64a2013-06-14 16:55:46 -070056Enumeration members have human readable string representations::
57
58 >>> print(Color.red)
59 Color.red
60
61...while their ``repr`` has more information::
62
63 >>> print(repr(Color.red))
64 <Color.red: 1>
65
66The *type* of an enumeration member is the enumeration it belongs to::
67
68 >>> type(Color.red)
69 <enum 'Color'>
70 >>> isinstance(Color.green, Color)
71 True
72 >>>
73
74Enum members also have a property that contains just their item name::
75
76 >>> print(Color.red.name)
77 red
78
79Enumerations support iteration, in definition order::
80
81 >>> class Shake(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070082 ... vanilla = 7
83 ... chocolate = 4
84 ... cookies = 9
85 ... mint = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -070086 ...
87 >>> for shake in Shake:
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070088 ... print(shake)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070089 ...
90 Shake.vanilla
91 Shake.chocolate
92 Shake.cookies
93 Shake.mint
94
95Enumeration members are hashable, so they can be used in dictionaries and sets::
96
97 >>> apples = {}
98 >>> apples[Color.red] = 'red delicious'
99 >>> apples[Color.green] = 'granny smith'
100 >>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'}
101 True
102
103
Ethan Furman3fe70b4a2013-06-28 14:02:34 -0700104Programmatic access to enumeration members and their attributes
105---------------------------------------------------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700106
107Sometimes it's useful to access members in enumerations programmatically (i.e.
108situations where ``Color.red`` won't do because the exact color is not known
109at program-writing time). ``Enum`` allows such access::
110
111 >>> Color(1)
112 <Color.red: 1>
113 >>> Color(3)
114 <Color.blue: 3>
115
116If you want to access enum members by *name*, use item access::
117
118 >>> Color['red']
119 <Color.red: 1>
120 >>> Color['green']
121 <Color.green: 2>
122
Ethan Furman3fe70b4a2013-06-28 14:02:34 -0700123If have an enum member and need its :attr:`name` or :attr:`value`::
124
125 >>> member = Color.red
126 >>> member.name
127 'red'
128 >>> member.value
129 1
130
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700131
132Duplicating enum members and values
133-----------------------------------
134
135Having two enum members with the same name is invalid::
136
137 >>> class Shape(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700138 ... square = 2
139 ... square = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700140 ...
141 Traceback (most recent call last):
142 ...
143 TypeError: Attempted to reuse key: 'square'
144
145However, two enum members are allowed to have the same value. Given two members
146A and B with the same value (and A defined first), B is an alias to A. By-value
147lookup of the value of A and B will return A. By-name lookup of B will also
148return A::
149
150 >>> class Shape(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700151 ... square = 2
152 ... diamond = 1
153 ... circle = 3
154 ... alias_for_square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700155 ...
156 >>> Shape.square
157 <Shape.square: 2>
158 >>> Shape.alias_for_square
159 <Shape.square: 2>
160 >>> Shape(2)
161 <Shape.square: 2>
162
Ethan Furman101e0742013-09-15 12:34:36 -0700163.. note::
164
165 Attempting to create a member with the same name as an already
166 defined attribute (another member, a method, etc.) or attempting to create
167 an attribute with the same name as a member is not allowed.
168
Ethan Furmanf24bb352013-07-18 17:05:39 -0700169
170Ensuring unique enumeration values
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700171----------------------------------
Ethan Furmanf24bb352013-07-18 17:05:39 -0700172
173By default, enumerations allow multiple names as aliases for the same value.
174When this behavior isn't desired, the following decorator can be used to
175ensure each value is used only once in the enumeration:
176
177.. decorator:: unique
178
179A :keyword:`class` decorator specifically for enumerations. It searches an
180enumeration's :attr:`__members__` gathering any aliases it finds; if any are
181found :exc:`ValueError` is raised with the details::
182
183 >>> from enum import Enum, unique
184 >>> @unique
185 ... class Mistake(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700186 ... one = 1
187 ... two = 2
188 ... three = 3
189 ... four = 3
190 ...
Ethan Furmanf24bb352013-07-18 17:05:39 -0700191 Traceback (most recent call last):
192 ...
193 ValueError: duplicate values found in <enum 'Mistake'>: four -> three
194
195
196Iteration
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700197---------
Ethan Furmanf24bb352013-07-18 17:05:39 -0700198
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700199Iterating over the members of an enum does not provide the aliases::
200
201 >>> list(Shape)
202 [<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>]
203
204The special attribute ``__members__`` is an ordered dictionary mapping names
205to members. It includes all names defined in the enumeration, including the
206aliases::
207
208 >>> for name, member in Shape.__members__.items():
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700209 ... name, member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700210 ...
211 ('square', <Shape.square: 2>)
212 ('diamond', <Shape.diamond: 1>)
213 ('circle', <Shape.circle: 3>)
214 ('alias_for_square', <Shape.square: 2>)
215
216The ``__members__`` attribute can be used for detailed programmatic access to
217the enumeration members. For example, finding all the aliases::
218
219 >>> [name for name, member in Shape.__members__.items() if member.name != name]
220 ['alias_for_square']
221
Ethan Furmanf24bb352013-07-18 17:05:39 -0700222
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700223Comparisons
224-----------
225
226Enumeration members are compared by identity::
227
228 >>> Color.red is Color.red
229 True
230 >>> Color.red is Color.blue
231 False
232 >>> Color.red is not Color.blue
233 True
234
235Ordered comparisons between enumeration values are *not* supported. Enum
236members are not integers (but see `IntEnum`_ below)::
237
238 >>> Color.red < Color.blue
239 Traceback (most recent call last):
240 File "<stdin>", line 1, in <module>
241 TypeError: unorderable types: Color() < Color()
242
243Equality comparisons are defined though::
244
245 >>> Color.blue == Color.red
246 False
247 >>> Color.blue != Color.red
248 True
249 >>> Color.blue == Color.blue
250 True
251
252Comparisons against non-enumeration values will always compare not equal
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300253(again, :class:`IntEnum` was explicitly designed to behave differently, see
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700254below)::
255
256 >>> Color.blue == 2
257 False
258
259
260Allowed members and attributes of enumerations
261----------------------------------------------
262
263The examples above use integers for enumeration values. Using integers is
264short and handy (and provided by default by the `Functional API`_), but not
265strictly enforced. In the vast majority of use-cases, one doesn't care what
266the actual value of an enumeration is. But if the value *is* important,
267enumerations can have arbitrary values.
268
269Enumerations are Python classes, and can have methods and special methods as
270usual. If we have this enumeration::
271
272 >>> class Mood(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700273 ... funky = 1
274 ... happy = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700275 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700276 ... def describe(self):
277 ... # self is the member here
278 ... return self.name, self.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700279 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700280 ... def __str__(self):
281 ... return 'my custom str! {0}'.format(self.value)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700282 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700283 ... @classmethod
284 ... def favorite_mood(cls):
285 ... # cls here is the enumeration
286 ... return cls.happy
287 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700288
289Then::
290
291 >>> Mood.favorite_mood()
292 <Mood.happy: 3>
293 >>> Mood.happy.describe()
294 ('happy', 3)
295 >>> str(Mood.funky)
296 'my custom str! 1'
297
298The rules for what is allowed are as follows: _sunder_ names (starting and
299ending with a single underscore) are reserved by enum and cannot be used;
300all other attributes defined within an enumeration will become members of this
301enumeration, with the exception of *__dunder__* names and descriptors (methods
302are also descriptors).
303
304Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then
305whatever value(s) were given to the enum member will be passed into those
306methods. See `Planet`_ for an example.
307
308
309Restricted subclassing of enumerations
310--------------------------------------
311
312Subclassing an enumeration is allowed only if the enumeration does not define
313any members. So this is forbidden::
314
315 >>> class MoreColor(Color):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700316 ... pink = 17
317 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700318 Traceback (most recent call last):
319 ...
320 TypeError: Cannot extend enumerations
321
322But this is allowed::
323
324 >>> class Foo(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700325 ... def some_behavior(self):
326 ... pass
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700327 ...
328 >>> class Bar(Foo):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700329 ... happy = 1
330 ... sad = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700331 ...
332
333Allowing subclassing of enums that define members would lead to a violation of
334some important invariants of types and instances. On the other hand, it makes
335sense to allow sharing some common behavior between a group of enumerations.
336(See `OrderedEnum`_ for an example.)
337
338
339Pickling
340--------
341
342Enumerations can be pickled and unpickled::
343
344 >>> from test.test_enum import Fruit
345 >>> from pickle import dumps, loads
346 >>> Fruit.tomato is loads(dumps(Fruit.tomato))
347 True
348
349The usual restrictions for pickling apply: picklable enums must be defined in
350the top level of a module, since unpickling requires them to be importable
351from that module.
352
353.. warning::
354
355 In order to support the singleton nature of enumeration members, pickle
356 protocol version 2 or higher must be used.
357
358
359Functional API
360--------------
361
362The :class:`Enum` class is callable, providing the following functional API::
363
364 >>> Animal = Enum('Animal', 'ant bee cat dog')
365 >>> Animal
366 <enum 'Animal'>
367 >>> Animal.ant
368 <Animal.ant: 1>
369 >>> Animal.ant.value
370 1
371 >>> list(Animal)
372 [<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>]
373
Serhiy Storchaka98b28fd2013-10-13 23:12:09 +0300374The semantics of this API resemble :class:`~collections.namedtuple`. The first
375argument of the call to :class:`Enum` is the name of the enumeration.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700376
377The second argument is the *source* of enumeration member names. It can be a
378whitespace-separated string of names, a sequence of names, a sequence of
3792-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to
380values. The last two options enable assigning arbitrary values to
381enumerations; the others auto-assign increasing integers starting with 1. A
382new class derived from :class:`Enum` is returned. In other words, the above
383assignment to :class:`Animal` is equivalent to::
384
385 >>> class Animals(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700386 ... ant = 1
387 ... bee = 2
388 ... cat = 3
389 ... dog = 4
390 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700391
Ethan Furmane2563462013-06-28 19:37:17 -0700392The reason for defaulting to ``1`` as the starting number and not ``0`` is
393that ``0`` is ``False`` in a boolean sense, but enum members all evaluate
394to ``True``.
395
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700396Pickling enums created with the functional API can be tricky as frame stack
397implementation details are used to try and figure out which module the
398enumeration is being created in (e.g. it will fail if you use a utility
399function in separate module, and also may not work on IronPython or Jython).
400The solution is to specify the module name explicitly as follows::
401
402 >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__)
403
404Derived Enumerations
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700405--------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700406
407IntEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700408^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700409
410A variation of :class:`Enum` is provided which is also a subclass of
411:class:`int`. Members of an :class:`IntEnum` can be compared to integers;
412by extension, integer enumerations of different types can also be compared
413to each other::
414
415 >>> from enum import IntEnum
416 >>> class Shape(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700417 ... circle = 1
418 ... square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700419 ...
420 >>> class Request(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700421 ... post = 1
422 ... get = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700423 ...
424 >>> Shape == 1
425 False
426 >>> Shape.circle == 1
427 True
428 >>> Shape.circle == Request.post
429 True
430
431However, they still can't be compared to standard :class:`Enum` enumerations::
432
433 >>> class Shape(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700434 ... circle = 1
435 ... square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700436 ...
437 >>> class Color(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700438 ... red = 1
439 ... green = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700440 ...
441 >>> Shape.circle == Color.red
442 False
443
444:class:`IntEnum` values behave like integers in other ways you'd expect::
445
446 >>> int(Shape.circle)
447 1
448 >>> ['a', 'b', 'c'][Shape.circle]
449 'b'
450 >>> [i for i in range(Shape.square)]
451 [0, 1]
452
453For the vast majority of code, :class:`Enum` is strongly recommended,
454since :class:`IntEnum` breaks some semantic promises of an enumeration (by
455being comparable to integers, and thus by transitivity to other
456unrelated enumerations). It should be used only in special cases where
457there's no other choice; for example, when integer constants are
458replaced with enumerations and backwards compatibility is required with code
459that still expects integers.
460
461
462Others
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700463^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700464
465While :class:`IntEnum` is part of the :mod:`enum` module, it would be very
466simple to implement independently::
467
468 class IntEnum(int, Enum):
469 pass
470
471This demonstrates how similar derived enumerations can be defined; for example
472a :class:`StrEnum` that mixes in :class:`str` instead of :class:`int`.
473
474Some rules:
475
4761. When subclassing :class:`Enum`, mix-in types must appear before
477 :class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum`
478 example above.
4792. While :class:`Enum` can have members of any type, once you mix in an
480 additional type, all the members must have values of that type, e.g.
481 :class:`int` above. This restriction does not apply to mix-ins which only
482 add methods and don't specify another data type such as :class:`int` or
483 :class:`str`.
4843. When another data type is mixed in, the :attr:`value` attribute is *not the
485 same* as the enum member itself, although it is equivalant and will compare
486 equal.
Ethan Furmanec15a822013-08-31 19:17:41 -07004874. %-style formatting: `%s` and `%r` call :class:`Enum`'s :meth:`__str__` and
488 :meth:`__repr__` respectively; other codes (such as `%i` or `%h` for
489 IntEnum) treat the enum member as its mixed-in type.
Ethan Furman455bfde2013-09-08 23:48:34 -07004905. :meth:`str.__format__` (or :func:`format`) will use the mixed-in
Ethan Furmanec15a822013-08-31 19:17:41 -0700491 type's :meth:`__format__`. If the :class:`Enum`'s :func:`str` or
492 :func:`repr` is desired use the `!s` or `!r` :class:`str` format codes.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700493
494
495Interesting examples
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700496--------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700497
498While :class:`Enum` and :class:`IntEnum` are expected to cover the majority of
499use-cases, they cannot cover them all. Here are recipes for some different
500types of enumerations that can be used directly, or as examples for creating
501one's own.
502
503
504AutoNumber
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700505^^^^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700506
507Avoids having to specify the value for each enumeration member::
508
509 >>> class AutoNumber(Enum):
510 ... def __new__(cls):
511 ... value = len(cls.__members__) + 1
512 ... obj = object.__new__(cls)
Ethan Furman90262622013-07-30 12:24:25 -0700513 ... obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700514 ... return obj
515 ...
516 >>> class Color(AutoNumber):
517 ... red = ()
518 ... green = ()
519 ... blue = ()
520 ...
521 >>> Color.green.value == 2
522 True
523
Ethan Furman9a1daf52013-09-27 22:58:06 -0700524.. note::
525
526 The :meth:`__new__` method, if defined, is used during creation of the Enum
527 members; it is then replaced by Enum's :meth:`__new__` which is used after
528 class creation for lookup of existing members. Due to the way Enums are
529 supposed to behave, there is no way to customize Enum's :meth:`__new__`.
530
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700531
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700532OrderedEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700533^^^^^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700534
535An ordered enumeration that is not based on :class:`IntEnum` and so maintains
536the normal :class:`Enum` invariants (such as not being comparable to other
537enumerations)::
538
539 >>> class OrderedEnum(Enum):
540 ... def __ge__(self, other):
541 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700542 ... return self.value >= other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700543 ... return NotImplemented
544 ... def __gt__(self, other):
545 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700546 ... return self.value > other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700547 ... return NotImplemented
548 ... def __le__(self, other):
549 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700550 ... return self.value <= other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700551 ... return NotImplemented
552 ... def __lt__(self, other):
553 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700554 ... return self.value < other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700555 ... return NotImplemented
556 ...
557 >>> class Grade(OrderedEnum):
558 ... A = 5
559 ... B = 4
560 ... C = 3
561 ... D = 2
562 ... F = 1
563 ...
564 >>> Grade.C < Grade.A
565 True
566
567
Ethan Furmanf24bb352013-07-18 17:05:39 -0700568DuplicateFreeEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700569^^^^^^^^^^^^^^^^^
Ethan Furmanf24bb352013-07-18 17:05:39 -0700570
571Raises an error if a duplicate member name is found instead of creating an
572alias::
573
574 >>> class DuplicateFreeEnum(Enum):
575 ... def __init__(self, *args):
576 ... cls = self.__class__
577 ... if any(self.value == e.value for e in cls):
578 ... a = self.name
579 ... e = cls(self.value).name
580 ... raise ValueError(
581 ... "aliases not allowed in DuplicateFreeEnum: %r --> %r"
582 ... % (a, e))
583 ...
584 >>> class Color(DuplicateFreeEnum):
585 ... red = 1
586 ... green = 2
587 ... blue = 3
588 ... grene = 2
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700589 ...
Ethan Furmanf24bb352013-07-18 17:05:39 -0700590 Traceback (most recent call last):
591 ...
592 ValueError: aliases not allowed in DuplicateFreeEnum: 'grene' --> 'green'
593
594.. note::
595
596 This is a useful example for subclassing Enum to add or change other
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300597 behaviors as well as disallowing aliases. If the only desired change is
Ezio Melotti17f1edd2013-10-05 04:26:06 +0300598 disallowing aliases, the :func:`unique` decorator can be used instead.
Ethan Furmanf24bb352013-07-18 17:05:39 -0700599
600
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700601Planet
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700602^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700603
604If :meth:`__new__` or :meth:`__init__` is defined the value of the enum member
605will be passed to those methods::
606
607 >>> class Planet(Enum):
608 ... MERCURY = (3.303e+23, 2.4397e6)
609 ... VENUS = (4.869e+24, 6.0518e6)
610 ... EARTH = (5.976e+24, 6.37814e6)
611 ... MARS = (6.421e+23, 3.3972e6)
612 ... JUPITER = (1.9e+27, 7.1492e7)
613 ... SATURN = (5.688e+26, 6.0268e7)
614 ... URANUS = (8.686e+25, 2.5559e7)
615 ... NEPTUNE = (1.024e+26, 2.4746e7)
616 ... def __init__(self, mass, radius):
617 ... self.mass = mass # in kilograms
618 ... self.radius = radius # in meters
619 ... @property
620 ... def surface_gravity(self):
621 ... # universal gravitational constant (m3 kg-1 s-2)
622 ... G = 6.67300E-11
623 ... return G * self.mass / (self.radius * self.radius)
624 ...
625 >>> Planet.EARTH.value
626 (5.976e+24, 6378140.0)
627 >>> Planet.EARTH.surface_gravity
628 9.802652743337129
Ethan Furman9a1daf52013-09-27 22:58:06 -0700629
630
631How are Enums different?
632------------------------
633
634Enums have a custom metaclass that affects many aspects of both derived Enum
635classes and their instances (members).
636
637
638Enum Classes
639^^^^^^^^^^^^
640
641The :class:`EnumMeta` metaclass is responsible for providing the
642:meth:`__contains__`, :meth:`__dir__`, :meth:`__iter__` and other methods that
643allow one to do things with an :class:`Enum` class that fail on a typical
644class, such as `list(Color)` or `some_var in Color`. :class:`EnumMeta` is
645responsible for ensuring that various other methods on the final :class:`Enum`
646class are correct (such as :meth:`__new__`, :meth:`__getnewargs__`,
647:meth:`__str__` and :meth:`__repr__`)
648
649
650Enum Members (aka instances)
651^^^^^^^^^^^^^^^^^^^^^^^^^^^^
652
653The most interesting thing about Enum members is that they are singletons.
654:class:`EnumMeta` creates them all while it is creating the :class:`Enum`
655class itself, and then puts a custom :meth:`__new__` in place to ensure
656that no new ones are ever instantiated by returning only the existing
657member instances.
658
659
660Finer Points
661^^^^^^^^^^^^
662
663Enum members are instances of an Enum class, and even though they are
664accessible as `EnumClass.member`, they are not accessible directly from
665the member::
666
667 >>> Color.red
668 <Color.red: 1>
669 >>> Color.red.blue
670 Traceback (most recent call last):
671 ...
672 AttributeError: 'Color' object has no attribute 'blue'
673
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300674Likewise, the :attr:`__members__` is only available on the class.
Ethan Furman9a1daf52013-09-27 22:58:06 -0700675
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300676If you give your :class:`Enum` subclass extra methods, like the `Planet`_
677class above, those methods will show up in a :func:`dir` of the member,
678but not of the class::
Ethan Furman9a1daf52013-09-27 22:58:06 -0700679
680 >>> dir(Planet)
681 ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
682 >>> dir(Planet.EARTH)
683 ['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
684
685A :meth:`__new__` method will only be used for the creation of the
686:class:`Enum` members -- after that it is replaced. This means if you wish to
687change how :class:`Enum` members are looked up you either have to write a
688helper function or a :func:`classmethod`.