mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +00:00
Revert "bpo-40066: [Enum] update str() and format() output (GH-30582)" (GH-30632)
This reverts commit acf7403f9b
.
This commit is contained in:
parent
7f4b69b907
commit
42a64c03ec
14 changed files with 2021 additions and 2087 deletions
|
@ -2,10 +2,15 @@
|
|||
Enum HOWTO
|
||||
==========
|
||||
|
||||
:Author: Ethan Furman <ethan at stoneleaf dot us>
|
||||
|
||||
.. _enum-basic-tutorial:
|
||||
|
||||
.. currentmodule:: enum
|
||||
|
||||
Basic Enum Tutorial
|
||||
-------------------
|
||||
|
||||
An :class:`Enum` is a set of symbolic names bound to unique values. They are
|
||||
similar to global variables, but they offer a more useful :func:`repr()`,
|
||||
grouping, type-safety, and a few other features.
|
||||
|
@ -23,14 +28,6 @@ selection of values. For example, the days of the week::
|
|||
... SATURDAY = 6
|
||||
... SUNDAY = 7
|
||||
|
||||
Or perhaps the RGB primary colors::
|
||||
|
||||
>>> from enum import Enum
|
||||
>>> class Color(Enum):
|
||||
... RED = 1
|
||||
... GREEN = 2
|
||||
... BLUE = 3
|
||||
|
||||
As you can see, creating an :class:`Enum` is as simple as writing a class that
|
||||
inherits from :class:`Enum` itself.
|
||||
|
||||
|
@ -44,14 +41,13 @@ important, but either way that value can be used to get the corresponding
|
|||
member::
|
||||
|
||||
>>> Weekday(3)
|
||||
<Weekday.WEDNESDAY: 3>
|
||||
Weekday.WEDNESDAY
|
||||
|
||||
As you can see, the ``repr()`` of a member shows the enum name, the member name,
|
||||
and the value. The ``str()`` of a member shows only the enum name and member
|
||||
name::
|
||||
As you can see, the ``repr()`` of a member shows the enum name and the
|
||||
member name. The ``str()`` on a member shows only its name::
|
||||
|
||||
>>> print(Weekday.THURSDAY)
|
||||
Weekday.THURSDAY
|
||||
THURSDAY
|
||||
|
||||
The *type* of an enumeration member is the enum it belongs to::
|
||||
|
||||
|
@ -101,8 +97,8 @@ The complete :class:`Weekday` enum now looks like this::
|
|||
Now we can find out what today is! Observe::
|
||||
|
||||
>>> from datetime import date
|
||||
>>> Weekday.from_date(date.today()) # doctest: +SKIP
|
||||
<Weekday.TUESDAY: 2>
|
||||
>>> Weekday.from_date(date.today())
|
||||
Weekday.TUESDAY
|
||||
|
||||
Of course, if you're reading this on some other day, you'll see that day instead.
|
||||
|
||||
|
@ -128,21 +124,21 @@ Just like the original :class:`Weekday` enum above, we can have a single selecti
|
|||
|
||||
>>> first_week_day = Weekday.MONDAY
|
||||
>>> first_week_day
|
||||
<Weekday.MONDAY: 1>
|
||||
Weekday.MONDAY
|
||||
|
||||
But :class:`Flag` also allows us to combine several members into a single
|
||||
variable::
|
||||
|
||||
>>> weekend = Weekday.SATURDAY | Weekday.SUNDAY
|
||||
>>> weekend
|
||||
<Weekday.SATURDAY|SUNDAY: 96>
|
||||
Weekday.SATURDAY|Weekday.SUNDAY
|
||||
|
||||
You can even iterate over a :class:`Flag` variable::
|
||||
|
||||
>>> for day in weekend:
|
||||
... print(day)
|
||||
Weekday.SATURDAY
|
||||
Weekday.SUNDAY
|
||||
SATURDAY
|
||||
SUNDAY
|
||||
|
||||
Okay, let's get some chores set up::
|
||||
|
||||
|
@ -177,7 +173,6 @@ yourself some work and use :func:`auto()` for the values::
|
|||
|
||||
.. _enum-advanced-tutorial:
|
||||
|
||||
|
||||
Programmatic access to enumeration members and their attributes
|
||||
---------------------------------------------------------------
|
||||
|
||||
|
@ -186,16 +181,16 @@ 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
|
||||
>>> Color(3)
|
||||
<Color.BLUE: 3>
|
||||
Color.BLUE
|
||||
|
||||
If you want to access enum members by *name*, use item access::
|
||||
|
||||
>>> Color['RED']
|
||||
<Color.RED: 1>
|
||||
Color.RED
|
||||
>>> Color['GREEN']
|
||||
<Color.GREEN: 2>
|
||||
Color.GREEN
|
||||
|
||||
If you have an enum member and need its :attr:`name` or :attr:`value`::
|
||||
|
||||
|
@ -217,7 +212,7 @@ Having two enum members with the same name is invalid::
|
|||
...
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: 'SQUARE' already defined as 2
|
||||
TypeError: 'SQUARE' already defined as: 2
|
||||
|
||||
However, an enum member can have other names associated with it. Given two
|
||||
entries ``A`` and ``B`` with the same value (and ``A`` defined first), ``B``
|
||||
|
@ -232,11 +227,11 @@ By-name lookup of ``B`` will also return the member ``A``::
|
|||
... ALIAS_FOR_SQUARE = 2
|
||||
...
|
||||
>>> Shape.SQUARE
|
||||
<Shape.SQUARE: 2>
|
||||
Shape.SQUARE
|
||||
>>> Shape.ALIAS_FOR_SQUARE
|
||||
<Shape.SQUARE: 2>
|
||||
Shape.SQUARE
|
||||
>>> Shape(2)
|
||||
<Shape.SQUARE: 2>
|
||||
Shape.SQUARE
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -304,7 +299,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, Shape.DIAMOND, Shape.CIRCLE]
|
||||
|
||||
The special attribute ``__members__`` is a read-only ordered mapping of names
|
||||
to members. It includes all names defined in the enumeration, including the
|
||||
|
@ -313,10 +308,10 @@ 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)
|
||||
('DIAMOND', Shape.DIAMOND)
|
||||
('CIRCLE', Shape.CIRCLE)
|
||||
('ALIAS_FOR_SQUARE', Shape.SQUARE)
|
||||
|
||||
The ``__members__`` attribute can be used for detailed programmatic access to
|
||||
the enumeration members. For example, finding all the aliases::
|
||||
|
@ -365,8 +360,8 @@ below)::
|
|||
Allowed members and attributes of enumerations
|
||||
----------------------------------------------
|
||||
|
||||
Most of the examples above use integers for enumeration values. Using integers
|
||||
is short and handy (and provided by default by the `Functional API`_), but not
|
||||
Most of the examples above use integers for enumeration values. Using integers is
|
||||
short and handy (and provided by default by the `Functional API`_), but not
|
||||
strictly enforced. In the vast majority of use-cases, one doesn't care what
|
||||
the actual value of an enumeration is. But if the value *is* important,
|
||||
enumerations can have arbitrary values.
|
||||
|
@ -394,7 +389,7 @@ usual. If we have this enumeration::
|
|||
Then::
|
||||
|
||||
>>> Mood.favorite_mood()
|
||||
<Mood.HAPPY: 3>
|
||||
Mood.HAPPY
|
||||
>>> Mood.HAPPY.describe()
|
||||
('HAPPY', 3)
|
||||
>>> str(Mood.FUNKY)
|
||||
|
@ -430,7 +425,7 @@ any members. So this is forbidden::
|
|||
...
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: <enum 'MoreColor'> cannot extend <enum 'Color'>
|
||||
TypeError: MoreColor: cannot extend enumeration 'Color'
|
||||
|
||||
But this is allowed::
|
||||
|
||||
|
@ -481,9 +476,11 @@ The :class:`Enum` class is callable, providing the following functional API::
|
|||
>>> Animal
|
||||
<enum 'Animal'>
|
||||
>>> Animal.ANT
|
||||
<Animal.ANT: 1>
|
||||
Animal.ANT
|
||||
>>> Animal.ANT.value
|
||||
1
|
||||
>>> list(Animal)
|
||||
[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
|
||||
[Animal.ANT, Animal.BEE, Animal.CAT, Animal.DOG]
|
||||
|
||||
The semantics of this API resemble :class:`~collections.namedtuple`. The first
|
||||
argument of the call to :class:`Enum` is the name of the enumeration.
|
||||
|
@ -628,7 +625,16 @@ StrEnum
|
|||
The second variation of :class:`Enum` that is provided is also a subclass of
|
||||
:class:`str`. Members of a :class:`StrEnum` can be compared to strings;
|
||||
by extension, string enumerations of different types can also be compared
|
||||
to each other.
|
||||
to each other. :class:`StrEnum` exists to help avoid the problem of getting
|
||||
an incorrect member::
|
||||
|
||||
>>> from enum import StrEnum
|
||||
>>> class Directions(StrEnum):
|
||||
... NORTH = 'north', # notice the trailing comma
|
||||
... SOUTH = 'south'
|
||||
|
||||
Before :class:`StrEnum`, ``Directions.NORTH`` would have been the :class:`tuple`
|
||||
``('north',)``.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
@ -639,8 +645,9 @@ IntFlag
|
|||
The next variation of :class:`Enum` provided, :class:`IntFlag`, is also based
|
||||
on :class:`int`. The difference being :class:`IntFlag` members can be combined
|
||||
using the bitwise operators (&, \|, ^, ~) and the result is still an
|
||||
:class:`IntFlag` member, if possible. Like :class:`IntEnum`, :class:`IntFlag`
|
||||
members are also integers and can be used wherever an :class:`int` is used.
|
||||
:class:`IntFlag` member, if possible. However, as the name implies, :class:`IntFlag`
|
||||
members also subclass :class:`int` and can be used wherever an :class:`int` is
|
||||
used.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -663,7 +670,7 @@ Sample :class:`IntFlag` class::
|
|||
... X = 1
|
||||
...
|
||||
>>> Perm.R | Perm.W
|
||||
<Perm.R|W: 6>
|
||||
Perm.R|Perm.W
|
||||
>>> Perm.R + Perm.W
|
||||
6
|
||||
>>> RW = Perm.R | Perm.W
|
||||
|
@ -678,11 +685,11 @@ It is also possible to name the combinations::
|
|||
... X = 1
|
||||
... RWX = 7
|
||||
>>> Perm.RWX
|
||||
<Perm.RWX: 7>
|
||||
Perm.RWX
|
||||
>>> ~Perm.RWX
|
||||
<Perm: 0>
|
||||
Perm(0)
|
||||
>>> Perm(7)
|
||||
<Perm.RWX: 7>
|
||||
Perm.RWX
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -695,7 +702,7 @@ Another important difference between :class:`IntFlag` and :class:`Enum` is that
|
|||
if no flags are set (the value is 0), its boolean evaluation is :data:`False`::
|
||||
|
||||
>>> Perm.R & Perm.X
|
||||
<Perm: 0>
|
||||
Perm(0)
|
||||
>>> bool(Perm.R & Perm.X)
|
||||
False
|
||||
|
||||
|
@ -703,7 +710,7 @@ Because :class:`IntFlag` members are also subclasses of :class:`int` they can
|
|||
be combined with them (but may lose :class:`IntFlag` membership::
|
||||
|
||||
>>> Perm.X | 4
|
||||
<Perm.R|X: 5>
|
||||
Perm.R|Perm.X
|
||||
|
||||
>>> Perm.X | 8
|
||||
9
|
||||
|
@ -719,7 +726,7 @@ be combined with them (but may lose :class:`IntFlag` membership::
|
|||
:class:`IntFlag` members can also be iterated over::
|
||||
|
||||
>>> list(RW)
|
||||
[<Perm.R: 4>, <Perm.W: 2>]
|
||||
[Perm.R, Perm.W]
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
@ -746,7 +753,7 @@ flags being set, the boolean evaluation is :data:`False`::
|
|||
... GREEN = auto()
|
||||
...
|
||||
>>> Color.RED & Color.GREEN
|
||||
<Color: 0>
|
||||
Color(0)
|
||||
>>> bool(Color.RED & Color.GREEN)
|
||||
False
|
||||
|
||||
|
@ -760,7 +767,7 @@ while combinations of flags won't::
|
|||
... WHITE = RED | BLUE | GREEN
|
||||
...
|
||||
>>> Color.WHITE
|
||||
<Color.WHITE: 7>
|
||||
Color.WHITE
|
||||
|
||||
Giving a name to the "no flags set" condition does not change its boolean
|
||||
value::
|
||||
|
@ -772,7 +779,7 @@ value::
|
|||
... GREEN = auto()
|
||||
...
|
||||
>>> Color.BLACK
|
||||
<Color.BLACK: 0>
|
||||
Color.BLACK
|
||||
>>> bool(Color.BLACK)
|
||||
False
|
||||
|
||||
|
@ -780,7 +787,7 @@ value::
|
|||
|
||||
>>> purple = Color.RED | Color.BLUE
|
||||
>>> list(purple)
|
||||
[<Color.RED: 1>, <Color.BLUE: 2>]
|
||||
[Color.RED, Color.BLUE]
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
@ -805,16 +812,16 @@ simple to implement independently::
|
|||
pass
|
||||
|
||||
This demonstrates how similar derived enumerations can be defined; for example
|
||||
a :class:`FloatEnum` that mixes in :class:`float` instead of :class:`int`.
|
||||
a :class:`StrEnum` that mixes in :class:`str` instead of :class:`int`.
|
||||
|
||||
Some rules:
|
||||
|
||||
1. When subclassing :class:`Enum`, mix-in types must appear before
|
||||
:class:`Enum` itself in the sequence of bases, as in the :class:`IntEnum`
|
||||
example above.
|
||||
2. Mix-in types must be subclassable. For example, :class:`bool` and
|
||||
:class:`range` are not subclassable and will throw an error during Enum
|
||||
creation if used as the mix-in type.
|
||||
2. Mix-in types must be subclassable. For example,
|
||||
:class:`bool` and :class:`range` are not subclassable
|
||||
and will throw an error during Enum creation if used as the mix-in type.
|
||||
3. While :class:`Enum` can have members of any type, once you mix in an
|
||||
additional type, all the members must have values of that type, e.g.
|
||||
:class:`int` above. This restriction does not apply to mix-ins which only
|
||||
|
@ -822,18 +829,15 @@ Some rules:
|
|||
4. When another data type is mixed in, the :attr:`value` attribute is *not the
|
||||
same* as the enum member itself, although it is equivalent and will compare
|
||||
equal.
|
||||
5. %-style formatting: ``%s`` and ``%r`` call the :class:`Enum` class's
|
||||
5. %-style formatting: `%s` and `%r` call the :class:`Enum` class's
|
||||
:meth:`__str__` and :meth:`__repr__` respectively; other codes (such as
|
||||
``%i`` or ``%h`` for IntEnum) treat the enum member as its mixed-in type.
|
||||
`%i` or `%h` for IntEnum) treat the enum member as its mixed-in type.
|
||||
6. :ref:`Formatted string literals <f-strings>`, :meth:`str.format`,
|
||||
and :func:`format` will use the enum's :meth:`__str__` method.
|
||||
|
||||
.. note::
|
||||
|
||||
Because :class:`IntEnum`, :class:`IntFlag`, and :class:`StrEnum` are
|
||||
designed to be drop-in replacements for existing constants, their
|
||||
:meth:`__str__` method has been reset to their data types
|
||||
:meth:`__str__` method.
|
||||
and :func:`format` will use the mixed-in type's :meth:`__format__`
|
||||
unless :meth:`__str__` or :meth:`__format__` is overridden in the subclass,
|
||||
in which case the overridden methods or :class:`Enum` methods will be used.
|
||||
Use the !s and !r format codes to force usage of the :class:`Enum` class's
|
||||
:meth:`__str__` and :meth:`__repr__` methods.
|
||||
|
||||
When to use :meth:`__new__` vs. :meth:`__init__`
|
||||
------------------------------------------------
|
||||
|
@ -862,10 +866,10 @@ want one of them to be the value::
|
|||
...
|
||||
|
||||
>>> print(Coordinate['PY'])
|
||||
Coordinate.PY
|
||||
PY
|
||||
|
||||
>>> print(Coordinate(3))
|
||||
Coordinate.VY
|
||||
VY
|
||||
|
||||
|
||||
Finer Points
|
||||
|
@ -923,8 +927,8 @@ and raise an error if the two do not match::
|
|||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: member order does not match _order_:
|
||||
['RED', 'BLUE', 'GREEN']
|
||||
['RED', 'GREEN', 'BLUE']
|
||||
['RED', 'BLUE', 'GREEN']
|
||||
['RED', 'GREEN', 'BLUE']
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -945,36 +949,35 @@ but remain normal attributes.
|
|||
""""""""""""""""""""
|
||||
|
||||
Enum members are instances of their enum class, and are normally accessed as
|
||||
``EnumClass.member``. In Python versions ``3.5`` to ``3.10`` you could access
|
||||
members from other members -- this practice was discouraged, and in ``3.11``
|
||||
:class:`Enum` returns to not allowing it::
|
||||
``EnumClass.member``. In Python versions ``3.5`` to ``3.9`` you could access
|
||||
members from other members -- this practice was discouraged, and in ``3.12``
|
||||
:class:`Enum` will return to not allowing it, while in ``3.10`` and ``3.11``
|
||||
it will raise a :exc:`DeprecationWarning`::
|
||||
|
||||
>>> class FieldTypes(Enum):
|
||||
... name = 0
|
||||
... value = 1
|
||||
... size = 2
|
||||
...
|
||||
>>> FieldTypes.value.size
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: <enum 'FieldTypes'> member has no attribute 'size'
|
||||
|
||||
>>> FieldTypes.value.size # doctest: +SKIP
|
||||
DeprecationWarning: accessing one member from another is not supported,
|
||||
and will be disabled in 3.12
|
||||
<FieldTypes.size: 2>
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
.. versionchanged:: 3.11
|
||||
|
||||
|
||||
Creating members that are mixed with other data types
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
When subclassing other data types, such as :class:`int` or :class:`str`, with
|
||||
an :class:`Enum`, all values after the ``=`` are passed to that data type's
|
||||
an :class:`Enum`, all values after the `=` are passed to that data type's
|
||||
constructor. For example::
|
||||
|
||||
>>> class MyEnum(IntEnum): # help(int) -> int(x, base=10) -> integer
|
||||
... example = '11', 16 # so x='11' and base=16
|
||||
...
|
||||
>>> MyEnum.example.value # and hex(11) is...
|
||||
>>> class MyEnum(IntEnum):
|
||||
... example = '11', 16 # '11' will be interpreted as a hexadecimal
|
||||
... # number
|
||||
>>> MyEnum.example.value
|
||||
17
|
||||
|
||||
|
||||
|
@ -997,12 +1000,13 @@ Plain :class:`Enum` classes always evaluate as :data:`True`.
|
|||
"""""""""""""""""""""""""""""
|
||||
|
||||
If you give your enum subclass extra methods, like the `Planet`_
|
||||
class below, those methods will show up in a :func:`dir` of the member,
|
||||
but not of the class::
|
||||
class below, those methods will show up in a :func:`dir` of the member and the
|
||||
class. Attributes defined in an :func:`__init__` method will only show up in a
|
||||
:func:`dir` of the member::
|
||||
|
||||
>>> dir(Planet) # doctest: +SKIP
|
||||
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
|
||||
>>> dir(Planet.EARTH) # doctest: +SKIP
|
||||
>>> dir(Planet)
|
||||
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__init__', '__members__', '__module__', 'surface_gravity']
|
||||
>>> dir(Planet.EARTH)
|
||||
['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value']
|
||||
|
||||
|
||||
|
@ -1021,10 +1025,19 @@ are comprised of a single bit::
|
|||
... CYAN = GREEN | BLUE
|
||||
...
|
||||
>>> Color(3) # named combination
|
||||
<Color.YELLOW: 3>
|
||||
Color.YELLOW
|
||||
>>> Color(7) # not named combination
|
||||
<Color.RED|GREEN|BLUE: 7>
|
||||
Color.RED|Color.GREEN|Color.BLUE
|
||||
|
||||
``StrEnum`` and :meth:`str.__str__`
|
||||
"""""""""""""""""""""""""""""""""""
|
||||
|
||||
An important difference between :class:`StrEnum` and other Enums is the
|
||||
:meth:`__str__` method; because :class:`StrEnum` members are strings, some
|
||||
parts of Python will read the string data directly, while others will call
|
||||
:meth:`str()`. To make those two operations have the same result,
|
||||
:meth:`StrEnum.__str__` will be the same as :meth:`str.__str__` so that
|
||||
``str(StrEnum.member) == StrEnum.member`` is true.
|
||||
|
||||
``Flag`` and ``IntFlag`` minutia
|
||||
""""""""""""""""""""""""""""""""
|
||||
|
@ -1047,16 +1060,16 @@ the following are true:
|
|||
- only canonical flags are returned during iteration::
|
||||
|
||||
>>> list(Color.WHITE)
|
||||
[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
|
||||
[Color.RED, Color.GREEN, Color.BLUE]
|
||||
|
||||
- negating a flag or flag set returns a new flag/flag set with the
|
||||
corresponding positive integer value::
|
||||
|
||||
>>> Color.BLUE
|
||||
<Color.BLUE: 4>
|
||||
Color.BLUE
|
||||
|
||||
>>> ~Color.BLUE
|
||||
<Color.RED|GREEN: 3>
|
||||
Color.RED|Color.GREEN
|
||||
|
||||
- names of pseudo-flags are constructed from their members' names::
|
||||
|
||||
|
@ -1066,29 +1079,25 @@ the following are true:
|
|||
- multi-bit flags, aka aliases, can be returned from operations::
|
||||
|
||||
>>> Color.RED | Color.BLUE
|
||||
<Color.PURPLE: 5>
|
||||
Color.PURPLE
|
||||
|
||||
>>> Color(7) # or Color(-1)
|
||||
<Color.WHITE: 7>
|
||||
Color.WHITE
|
||||
|
||||
>>> Color(0)
|
||||
<Color.BLACK: 0>
|
||||
Color.BLACK
|
||||
|
||||
- membership / containment checking: zero-valued flags are always considered
|
||||
to be contained::
|
||||
- membership / containment checking has changed slightly -- zero-valued flags
|
||||
are never considered to be contained::
|
||||
|
||||
>>> Color.BLACK in Color.WHITE
|
||||
True
|
||||
False
|
||||
|
||||
otherwise, only if all bits of one flag are in the other flag will True
|
||||
be returned::
|
||||
otherwise, if all bits of one flag are in the other flag, True is returned::
|
||||
|
||||
>>> Color.PURPLE in Color.WHITE
|
||||
True
|
||||
|
||||
>>> Color.GREEN in Color.PURPLE
|
||||
False
|
||||
|
||||
There is a new boundary mechanism that controls how out-of-range / invalid
|
||||
bits are handled: ``STRICT``, ``CONFORM``, ``EJECT``, and ``KEEP``:
|
||||
|
||||
|
@ -1172,7 +1181,7 @@ Using :class:`auto` would look like::
|
|||
... GREEN = auto()
|
||||
...
|
||||
>>> Color.GREEN
|
||||
<Color.GREEN: 3>
|
||||
<Color.GREEN>
|
||||
|
||||
|
||||
Using :class:`object`
|
||||
|
@ -1185,24 +1194,10 @@ Using :class:`object` would look like::
|
|||
... GREEN = object()
|
||||
... BLUE = object()
|
||||
...
|
||||
>>> Color.GREEN # doctest: +SKIP
|
||||
<Color.GREEN: <object object at 0x...>>
|
||||
|
||||
This is also a good example of why you might want to write your own
|
||||
:meth:`__repr__`::
|
||||
|
||||
>>> class Color(Enum):
|
||||
... RED = object()
|
||||
... GREEN = object()
|
||||
... BLUE = object()
|
||||
... def __repr__(self):
|
||||
... return "<%s.%s>" % (self.__class__.__name__, self._name_)
|
||||
...
|
||||
>>> Color.GREEN
|
||||
<Color.GREEN>
|
||||
|
||||
|
||||
|
||||
Using a descriptive string
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
|
@ -1214,7 +1209,9 @@ Using a string as the value would look like::
|
|||
... BLUE = 'too fast!'
|
||||
...
|
||||
>>> Color.GREEN
|
||||
<Color.GREEN: 'go'>
|
||||
<Color.GREEN>
|
||||
>>> Color.GREEN.value
|
||||
'go'
|
||||
|
||||
|
||||
Using a custom :meth:`__new__`
|
||||
|
@ -1235,7 +1232,9 @@ Using an auto-numbering :meth:`__new__` would look like::
|
|||
... BLUE = ()
|
||||
...
|
||||
>>> Color.GREEN
|
||||
<Color.GREEN: 2>
|
||||
<Color.GREEN>
|
||||
>>> Color.GREEN.value
|
||||
2
|
||||
|
||||
To make a more general purpose ``AutoNumber``, add ``*args`` to the signature::
|
||||
|
||||
|
@ -1258,7 +1257,7 @@ to handle any extra arguments::
|
|||
... BLEACHED_CORAL = () # New color, no Pantone code yet!
|
||||
...
|
||||
>>> Swatch.SEA_GREEN
|
||||
<Swatch.SEA_GREEN: 2>
|
||||
<Swatch.SEA_GREEN>
|
||||
>>> Swatch.SEA_GREEN.pantone
|
||||
'1246'
|
||||
>>> Swatch.BLEACHED_CORAL.pantone
|
||||
|
@ -1385,9 +1384,30 @@ An example to show the :attr:`_ignore_` attribute in use::
|
|||
... Period['day_%d' % i] = i
|
||||
...
|
||||
>>> list(Period)[:2]
|
||||
[<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>]
|
||||
[Period.day_0, Period.day_1]
|
||||
>>> list(Period)[-2:]
|
||||
[<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]
|
||||
[Period.day_365, Period.day_366]
|
||||
|
||||
|
||||
Conforming input to Flag
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To create a :class:`Flag` enum that is more resilient to out-of-bounds results
|
||||
from mathematical operations, you can use the :attr:`FlagBoundary.CONFORM`
|
||||
setting::
|
||||
|
||||
>>> from enum import Flag, CONFORM, auto
|
||||
>>> class Weekday(Flag, boundary=CONFORM):
|
||||
... MONDAY = auto()
|
||||
... TUESDAY = auto()
|
||||
... WEDNESDAY = auto()
|
||||
... THURSDAY = auto()
|
||||
... FRIDAY = auto()
|
||||
... SATURDAY = auto()
|
||||
... SUNDAY = auto()
|
||||
>>> today = Weekday.TUESDAY
|
||||
>>> Weekday(today + 22) # what day is three weeks from tomorrow?
|
||||
>>> Weekday.WEDNESDAY
|
||||
|
||||
|
||||
.. _enumtype-examples:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue