blob: 2d206107b43c7ef0061a7cf79a510f1bffae36ab [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
R David Murrayfd1ff1c2013-12-20 14:20:49 -050012.. versionadded:: 3.4
13
Ethan Furman6b3d64a2013-06-14 16:55:46 -070014**Source code:** :source:`Lib/enum.py`
15
16----------------
17
18An enumeration is a set of symbolic names (members) bound to unique, constant
19values. Within an enumeration, the members can be compared by identity, and
20the enumeration itself can be iterated over.
21
22This module defines two enumeration classes that can be used to define unique
Ethan Furmanf24bb352013-07-18 17:05:39 -070023sets of names and values: :class:`Enum` and :class:`IntEnum`. It also defines
24one decorator, :func:`unique`, that ensures only unique member values are
25present in an enumeration.
26
Ethan Furman6b3d64a2013-06-14 16:55:46 -070027
28Creating an Enum
29----------------
30
31Enumerations are created using the :keyword:`class` syntax, which makes them
32easy to read and write. An alternative creation method is described in
33`Functional API`_. To define an enumeration, subclass :class:`Enum` as
34follows::
35
36 >>> from enum import Enum
37 >>> class Color(Enum):
38 ... red = 1
39 ... green = 2
40 ... blue = 3
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070041 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -070042
Ethan Furman455bfde2013-09-08 23:48:34 -070043.. note:: Nomenclature
44
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070045 - The class :class:`Color` is an *enumeration* (or *enum*)
46 - The attributes :attr:`Color.red`, :attr:`Color.green`, etc., are
47 *enumeration members* (or *enum members*).
48 - The enum members have *names* and *values* (the name of
49 :attr:`Color.red` is ``red``, the value of :attr:`Color.blue` is
50 ``3``, etc.)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070051
Ethan Furman9a1daf52013-09-27 22:58:06 -070052.. note::
53
54 Even though we use the :keyword:`class` syntax to create Enums, Enums
55 are not normal Python classes. See `How are Enums different?`_ for
56 more details.
57
Ethan Furman6b3d64a2013-06-14 16:55:46 -070058Enumeration members have human readable string representations::
59
60 >>> print(Color.red)
61 Color.red
62
63...while their ``repr`` has more information::
64
65 >>> print(repr(Color.red))
66 <Color.red: 1>
67
68The *type* of an enumeration member is the enumeration it belongs to::
69
70 >>> type(Color.red)
71 <enum 'Color'>
72 >>> isinstance(Color.green, Color)
73 True
74 >>>
75
76Enum members also have a property that contains just their item name::
77
78 >>> print(Color.red.name)
79 red
80
81Enumerations support iteration, in definition order::
82
83 >>> class Shake(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070084 ... vanilla = 7
85 ... chocolate = 4
86 ... cookies = 9
87 ... mint = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -070088 ...
89 >>> for shake in Shake:
Ethan Furmaned0bf8a2013-09-06 19:53:30 -070090 ... print(shake)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070091 ...
92 Shake.vanilla
93 Shake.chocolate
94 Shake.cookies
95 Shake.mint
96
97Enumeration members are hashable, so they can be used in dictionaries and sets::
98
99 >>> apples = {}
100 >>> apples[Color.red] = 'red delicious'
101 >>> apples[Color.green] = 'granny smith'
102 >>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'}
103 True
104
105
Ethan Furman3fe70b4a2013-06-28 14:02:34 -0700106Programmatic access to enumeration members and their attributes
107---------------------------------------------------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700108
109Sometimes it's useful to access members in enumerations programmatically (i.e.
110situations where ``Color.red`` won't do because the exact color is not known
111at program-writing time). ``Enum`` allows such access::
112
113 >>> Color(1)
114 <Color.red: 1>
115 >>> Color(3)
116 <Color.blue: 3>
117
118If you want to access enum members by *name*, use item access::
119
120 >>> Color['red']
121 <Color.red: 1>
122 >>> Color['green']
123 <Color.green: 2>
124
Ethan Furman3fe70b4a2013-06-28 14:02:34 -0700125If have an enum member and need its :attr:`name` or :attr:`value`::
126
127 >>> member = Color.red
128 >>> member.name
129 'red'
130 >>> member.value
131 1
132
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700133
134Duplicating enum members and values
135-----------------------------------
136
137Having two enum members with the same name is invalid::
138
139 >>> class Shape(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700140 ... square = 2
141 ... square = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700142 ...
143 Traceback (most recent call last):
144 ...
145 TypeError: Attempted to reuse key: 'square'
146
147However, two enum members are allowed to have the same value. Given two members
148A and B with the same value (and A defined first), B is an alias to A. By-value
149lookup of the value of A and B will return A. By-name lookup of B will also
150return A::
151
152 >>> class Shape(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700153 ... square = 2
154 ... diamond = 1
155 ... circle = 3
156 ... alias_for_square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700157 ...
158 >>> Shape.square
159 <Shape.square: 2>
160 >>> Shape.alias_for_square
161 <Shape.square: 2>
162 >>> Shape(2)
163 <Shape.square: 2>
164
Ethan Furman101e0742013-09-15 12:34:36 -0700165.. note::
166
167 Attempting to create a member with the same name as an already
168 defined attribute (another member, a method, etc.) or attempting to create
169 an attribute with the same name as a member is not allowed.
170
Ethan Furmanf24bb352013-07-18 17:05:39 -0700171
172Ensuring unique enumeration values
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700173----------------------------------
Ethan Furmanf24bb352013-07-18 17:05:39 -0700174
175By default, enumerations allow multiple names as aliases for the same value.
176When this behavior isn't desired, the following decorator can be used to
177ensure each value is used only once in the enumeration:
178
179.. decorator:: unique
180
181A :keyword:`class` decorator specifically for enumerations. It searches an
182enumeration's :attr:`__members__` gathering any aliases it finds; if any are
183found :exc:`ValueError` is raised with the details::
184
185 >>> from enum import Enum, unique
186 >>> @unique
187 ... class Mistake(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700188 ... one = 1
189 ... two = 2
190 ... three = 3
191 ... four = 3
192 ...
Ethan Furmanf24bb352013-07-18 17:05:39 -0700193 Traceback (most recent call last):
194 ...
195 ValueError: duplicate values found in <enum 'Mistake'>: four -> three
196
197
198Iteration
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700199---------
Ethan Furmanf24bb352013-07-18 17:05:39 -0700200
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700201Iterating over the members of an enum does not provide the aliases::
202
203 >>> list(Shape)
204 [<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>]
205
206The special attribute ``__members__`` is an ordered dictionary mapping names
207to members. It includes all names defined in the enumeration, including the
208aliases::
209
210 >>> for name, member in Shape.__members__.items():
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700211 ... name, member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700212 ...
213 ('square', <Shape.square: 2>)
214 ('diamond', <Shape.diamond: 1>)
215 ('circle', <Shape.circle: 3>)
216 ('alias_for_square', <Shape.square: 2>)
217
218The ``__members__`` attribute can be used for detailed programmatic access to
219the enumeration members. For example, finding all the aliases::
220
221 >>> [name for name, member in Shape.__members__.items() if member.name != name]
222 ['alias_for_square']
223
Ethan Furmanf24bb352013-07-18 17:05:39 -0700224
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700225Comparisons
226-----------
227
228Enumeration members are compared by identity::
229
230 >>> Color.red is Color.red
231 True
232 >>> Color.red is Color.blue
233 False
234 >>> Color.red is not Color.blue
235 True
236
237Ordered comparisons between enumeration values are *not* supported. Enum
238members are not integers (but see `IntEnum`_ below)::
239
240 >>> Color.red < Color.blue
241 Traceback (most recent call last):
242 File "<stdin>", line 1, in <module>
243 TypeError: unorderable types: Color() < Color()
244
245Equality comparisons are defined though::
246
247 >>> Color.blue == Color.red
248 False
249 >>> Color.blue != Color.red
250 True
251 >>> Color.blue == Color.blue
252 True
253
254Comparisons against non-enumeration values will always compare not equal
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300255(again, :class:`IntEnum` was explicitly designed to behave differently, see
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700256below)::
257
258 >>> Color.blue == 2
259 False
260
261
262Allowed members and attributes of enumerations
263----------------------------------------------
264
265The examples above use integers for enumeration values. Using integers is
266short and handy (and provided by default by the `Functional API`_), but not
267strictly enforced. In the vast majority of use-cases, one doesn't care what
268the actual value of an enumeration is. But if the value *is* important,
269enumerations can have arbitrary values.
270
271Enumerations are Python classes, and can have methods and special methods as
272usual. If we have this enumeration::
273
274 >>> class Mood(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700275 ... funky = 1
276 ... happy = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700277 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700278 ... def describe(self):
279 ... # self is the member here
280 ... return self.name, self.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700281 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700282 ... def __str__(self):
283 ... return 'my custom str! {0}'.format(self.value)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700284 ...
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700285 ... @classmethod
286 ... def favorite_mood(cls):
287 ... # cls here is the enumeration
288 ... return cls.happy
289 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700290
291Then::
292
293 >>> Mood.favorite_mood()
294 <Mood.happy: 3>
295 >>> Mood.happy.describe()
296 ('happy', 3)
297 >>> str(Mood.funky)
298 'my custom str! 1'
299
300The rules for what is allowed are as follows: _sunder_ names (starting and
301ending with a single underscore) are reserved by enum and cannot be used;
302all other attributes defined within an enumeration will become members of this
303enumeration, with the exception of *__dunder__* names and descriptors (methods
304are also descriptors).
305
306Note: if your enumeration defines :meth:`__new__` and/or :meth:`__init__` then
307whatever value(s) were given to the enum member will be passed into those
308methods. See `Planet`_ for an example.
309
310
311Restricted subclassing of enumerations
312--------------------------------------
313
314Subclassing an enumeration is allowed only if the enumeration does not define
315any members. So this is forbidden::
316
317 >>> class MoreColor(Color):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700318 ... pink = 17
319 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700320 Traceback (most recent call last):
321 ...
322 TypeError: Cannot extend enumerations
323
324But this is allowed::
325
326 >>> class Foo(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700327 ... def some_behavior(self):
328 ... pass
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700329 ...
330 >>> class Bar(Foo):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700331 ... happy = 1
332 ... sad = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700333 ...
334
335Allowing subclassing of enums that define members would lead to a violation of
336some important invariants of types and instances. On the other hand, it makes
337sense to allow sharing some common behavior between a group of enumerations.
338(See `OrderedEnum`_ for an example.)
339
340
341Pickling
342--------
343
344Enumerations can be pickled and unpickled::
345
346 >>> from test.test_enum import Fruit
347 >>> from pickle import dumps, loads
348 >>> Fruit.tomato is loads(dumps(Fruit.tomato))
349 True
350
351The usual restrictions for pickling apply: picklable enums must be defined in
352the top level of a module, since unpickling requires them to be importable
353from that module.
354
355.. warning::
356
357 In order to support the singleton nature of enumeration members, pickle
358 protocol version 2 or higher must be used.
359
360
361Functional API
362--------------
363
364The :class:`Enum` class is callable, providing the following functional API::
365
366 >>> Animal = Enum('Animal', 'ant bee cat dog')
367 >>> Animal
368 <enum 'Animal'>
369 >>> Animal.ant
370 <Animal.ant: 1>
371 >>> Animal.ant.value
372 1
373 >>> list(Animal)
374 [<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>]
375
Serhiy Storchaka98b28fd2013-10-13 23:12:09 +0300376The semantics of this API resemble :class:`~collections.namedtuple`. The first
377argument of the call to :class:`Enum` is the name of the enumeration.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700378
379The second argument is the *source* of enumeration member names. It can be a
380whitespace-separated string of names, a sequence of names, a sequence of
3812-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to
382values. The last two options enable assigning arbitrary values to
383enumerations; the others auto-assign increasing integers starting with 1. A
384new class derived from :class:`Enum` is returned. In other words, the above
385assignment to :class:`Animal` is equivalent to::
386
387 >>> class Animals(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700388 ... ant = 1
389 ... bee = 2
390 ... cat = 3
391 ... dog = 4
392 ...
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700393
Ethan Furmane2563462013-06-28 19:37:17 -0700394The reason for defaulting to ``1`` as the starting number and not ``0`` is
395that ``0`` is ``False`` in a boolean sense, but enum members all evaluate
396to ``True``.
397
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700398Pickling enums created with the functional API can be tricky as frame stack
399implementation details are used to try and figure out which module the
400enumeration is being created in (e.g. it will fail if you use a utility
401function in separate module, and also may not work on IronPython or Jython).
402The solution is to specify the module name explicitly as follows::
403
404 >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__)
405
406Derived Enumerations
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700407--------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700408
409IntEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700410^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700411
412A variation of :class:`Enum` is provided which is also a subclass of
413:class:`int`. Members of an :class:`IntEnum` can be compared to integers;
414by extension, integer enumerations of different types can also be compared
415to each other::
416
417 >>> from enum import IntEnum
418 >>> class Shape(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700419 ... circle = 1
420 ... square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700421 ...
422 >>> class Request(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700423 ... post = 1
424 ... get = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700425 ...
426 >>> Shape == 1
427 False
428 >>> Shape.circle == 1
429 True
430 >>> Shape.circle == Request.post
431 True
432
433However, they still can't be compared to standard :class:`Enum` enumerations::
434
435 >>> class Shape(IntEnum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700436 ... circle = 1
437 ... square = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700438 ...
439 >>> class Color(Enum):
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700440 ... red = 1
441 ... green = 2
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700442 ...
443 >>> Shape.circle == Color.red
444 False
445
446:class:`IntEnum` values behave like integers in other ways you'd expect::
447
448 >>> int(Shape.circle)
449 1
450 >>> ['a', 'b', 'c'][Shape.circle]
451 'b'
452 >>> [i for i in range(Shape.square)]
453 [0, 1]
454
455For the vast majority of code, :class:`Enum` is strongly recommended,
456since :class:`IntEnum` breaks some semantic promises of an enumeration (by
457being comparable to integers, and thus by transitivity to other
458unrelated enumerations). It should be used only in special cases where
459there's no other choice; for example, when integer constants are
460replaced with enumerations and backwards compatibility is required with code
461that still expects integers.
462
463
464Others
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700465^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700466
467While :class:`IntEnum` is part of the :mod:`enum` module, it would be very
468simple to implement independently::
469
470 class IntEnum(int, Enum):
471 pass
472
473This demonstrates how similar derived enumerations can be defined; for example
474a :class:`StrEnum` that mixes in :class:`str` instead of :class:`int`.
475
476Some rules:
477
4781. When subclassing :class:`Enum`, mix-in types must appear before
479 :class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum`
480 example above.
4812. While :class:`Enum` can have members of any type, once you mix in an
482 additional type, all the members must have values of that type, e.g.
483 :class:`int` above. This restriction does not apply to mix-ins which only
484 add methods and don't specify another data type such as :class:`int` or
485 :class:`str`.
4863. When another data type is mixed in, the :attr:`value` attribute is *not the
487 same* as the enum member itself, although it is equivalant and will compare
488 equal.
Ethan Furmanec15a822013-08-31 19:17:41 -07004894. %-style formatting: `%s` and `%r` call :class:`Enum`'s :meth:`__str__` and
490 :meth:`__repr__` respectively; other codes (such as `%i` or `%h` for
491 IntEnum) treat the enum member as its mixed-in type.
Ethan Furman455bfde2013-09-08 23:48:34 -07004925. :meth:`str.__format__` (or :func:`format`) will use the mixed-in
Ethan Furmanec15a822013-08-31 19:17:41 -0700493 type's :meth:`__format__`. If the :class:`Enum`'s :func:`str` or
494 :func:`repr` is desired use the `!s` or `!r` :class:`str` format codes.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700495
496
497Interesting examples
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700498--------------------
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700499
500While :class:`Enum` and :class:`IntEnum` are expected to cover the majority of
501use-cases, they cannot cover them all. Here are recipes for some different
502types of enumerations that can be used directly, or as examples for creating
503one's own.
504
505
506AutoNumber
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700507^^^^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700508
509Avoids having to specify the value for each enumeration member::
510
511 >>> class AutoNumber(Enum):
512 ... def __new__(cls):
513 ... value = len(cls.__members__) + 1
514 ... obj = object.__new__(cls)
Ethan Furman90262622013-07-30 12:24:25 -0700515 ... obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700516 ... return obj
517 ...
518 >>> class Color(AutoNumber):
519 ... red = ()
520 ... green = ()
521 ... blue = ()
522 ...
523 >>> Color.green.value == 2
524 True
525
Ethan Furman9a1daf52013-09-27 22:58:06 -0700526.. note::
527
528 The :meth:`__new__` method, if defined, is used during creation of the Enum
529 members; it is then replaced by Enum's :meth:`__new__` which is used after
530 class creation for lookup of existing members. Due to the way Enums are
531 supposed to behave, there is no way to customize Enum's :meth:`__new__`.
532
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700533
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700534OrderedEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700535^^^^^^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700536
537An ordered enumeration that is not based on :class:`IntEnum` and so maintains
538the normal :class:`Enum` invariants (such as not being comparable to other
539enumerations)::
540
541 >>> class OrderedEnum(Enum):
542 ... def __ge__(self, other):
543 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700544 ... return self.value >= other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700545 ... return NotImplemented
546 ... def __gt__(self, other):
547 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700548 ... return self.value > other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700549 ... return NotImplemented
550 ... def __le__(self, other):
551 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700552 ... return self.value <= other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700553 ... return NotImplemented
554 ... def __lt__(self, other):
555 ... if self.__class__ is other.__class__:
Ethan Furman90262622013-07-30 12:24:25 -0700556 ... return self.value < other.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700557 ... return NotImplemented
558 ...
559 >>> class Grade(OrderedEnum):
560 ... A = 5
561 ... B = 4
562 ... C = 3
563 ... D = 2
564 ... F = 1
565 ...
566 >>> Grade.C < Grade.A
567 True
568
569
Ethan Furmanf24bb352013-07-18 17:05:39 -0700570DuplicateFreeEnum
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700571^^^^^^^^^^^^^^^^^
Ethan Furmanf24bb352013-07-18 17:05:39 -0700572
573Raises an error if a duplicate member name is found instead of creating an
574alias::
575
576 >>> class DuplicateFreeEnum(Enum):
577 ... def __init__(self, *args):
578 ... cls = self.__class__
579 ... if any(self.value == e.value for e in cls):
580 ... a = self.name
581 ... e = cls(self.value).name
582 ... raise ValueError(
583 ... "aliases not allowed in DuplicateFreeEnum: %r --> %r"
584 ... % (a, e))
585 ...
586 >>> class Color(DuplicateFreeEnum):
587 ... red = 1
588 ... green = 2
589 ... blue = 3
590 ... grene = 2
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700591 ...
Ethan Furmanf24bb352013-07-18 17:05:39 -0700592 Traceback (most recent call last):
593 ...
594 ValueError: aliases not allowed in DuplicateFreeEnum: 'grene' --> 'green'
595
596.. note::
597
598 This is a useful example for subclassing Enum to add or change other
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300599 behaviors as well as disallowing aliases. If the only desired change is
Ezio Melotti17f1edd2013-10-05 04:26:06 +0300600 disallowing aliases, the :func:`unique` decorator can be used instead.
Ethan Furmanf24bb352013-07-18 17:05:39 -0700601
602
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700603Planet
Ethan Furmaned0bf8a2013-09-06 19:53:30 -0700604^^^^^^
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700605
606If :meth:`__new__` or :meth:`__init__` is defined the value of the enum member
607will be passed to those methods::
608
609 >>> class Planet(Enum):
610 ... MERCURY = (3.303e+23, 2.4397e6)
611 ... VENUS = (4.869e+24, 6.0518e6)
612 ... EARTH = (5.976e+24, 6.37814e6)
613 ... MARS = (6.421e+23, 3.3972e6)
614 ... JUPITER = (1.9e+27, 7.1492e7)
615 ... SATURN = (5.688e+26, 6.0268e7)
616 ... URANUS = (8.686e+25, 2.5559e7)
617 ... NEPTUNE = (1.024e+26, 2.4746e7)
618 ... def __init__(self, mass, radius):
619 ... self.mass = mass # in kilograms
620 ... self.radius = radius # in meters
621 ... @property
622 ... def surface_gravity(self):
623 ... # universal gravitational constant (m3 kg-1 s-2)
624 ... G = 6.67300E-11
625 ... return G * self.mass / (self.radius * self.radius)
626 ...
627 >>> Planet.EARTH.value
628 (5.976e+24, 6378140.0)
629 >>> Planet.EARTH.surface_gravity
630 9.802652743337129
Ethan Furman9a1daf52013-09-27 22:58:06 -0700631
632
633How are Enums different?
634------------------------
635
636Enums have a custom metaclass that affects many aspects of both derived Enum
637classes and their instances (members).
638
639
640Enum Classes
641^^^^^^^^^^^^
642
643The :class:`EnumMeta` metaclass is responsible for providing the
644:meth:`__contains__`, :meth:`__dir__`, :meth:`__iter__` and other methods that
645allow one to do things with an :class:`Enum` class that fail on a typical
646class, such as `list(Color)` or `some_var in Color`. :class:`EnumMeta` is
647responsible for ensuring that various other methods on the final :class:`Enum`
648class are correct (such as :meth:`__new__`, :meth:`__getnewargs__`,
649:meth:`__str__` and :meth:`__repr__`)
650
651
652Enum Members (aka instances)
653^^^^^^^^^^^^^^^^^^^^^^^^^^^^
654
655The most interesting thing about Enum members is that they are singletons.
656:class:`EnumMeta` creates them all while it is creating the :class:`Enum`
657class itself, and then puts a custom :meth:`__new__` in place to ensure
658that no new ones are ever instantiated by returning only the existing
659member instances.
660
661
662Finer Points
663^^^^^^^^^^^^
664
665Enum members are instances of an Enum class, and even though they are
666accessible as `EnumClass.member`, they are not accessible directly from
667the member::
668
669 >>> Color.red
670 <Color.red: 1>
671 >>> Color.red.blue
672 Traceback (most recent call last):
673 ...
674 AttributeError: 'Color' object has no attribute 'blue'
675
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300676Likewise, the :attr:`__members__` is only available on the class.
Ethan Furman9a1daf52013-09-27 22:58:06 -0700677
Ezio Melotti93d7dda2013-10-05 04:13:18 +0300678If you give your :class:`Enum` subclass extra methods, like the `Planet`_
679class above, those methods will show up in a :func:`dir` of the member,
680but not of the class::
Ethan Furman9a1daf52013-09-27 22:58:06 -0700681
682 >>> dir(Planet)
683 ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
684 >>> dir(Planet.EARTH)
685 ['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
686
687A :meth:`__new__` method will only be used for the creation of the
688:class:`Enum` members -- after that it is replaced. This means if you wish to
689change how :class:`Enum` members are looked up you either have to write a
690helper function or a :func:`classmethod`.