381

I'm using Enum4 library to create an enum class as follows:

class Color(Enum):
    RED = 1
    BLUE = 2

I want to print [1, 2] as a list somewhere. How can I achieve this?

cdignam
  • 1,376
  • 1
  • 15
  • 21
user1159517
  • 5,390
  • 8
  • 30
  • 47

17 Answers17

886

You can do the following:

[e.value for e in Color]
Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
141

Based on the answer by @Jeff, refactored to use a classmethod so that you can reuse the same code for any of your enums:

from enum import Enum

class ExtendedEnum(Enum):

    @classmethod
    def list(cls):
        return list(map(lambda c: c.value, cls))

class OperationType(ExtendedEnum):
    CREATE = 'CREATE'
    STATUS = 'STATUS'
    EXPAND = 'EXPAND'
    DELETE = 'DELETE'

print(OperationType.list())

Produces:

['CREATE', 'STATUS', 'EXPAND', 'DELETE']
blueFast
  • 41,341
  • 63
  • 198
  • 344
  • 2
    Beautiful! I've been trying to do exactly this for about an hour but was use not grasping the need for the classmethod. I was attempting to just subclass and add a property attribute, but could not get the super().__init__() to properly pass arguments to Enum. Thanks! – Jesse Reich Oct 21 '21 at 18:37
  • 9
    Why make things extra confusing with a map? Guido wanted to remove them because you can do the same thing with generators more clearly. `[c.value for c in cls]` is the preferred syntax in Python. (Doesn't matter here but one benefit is avoiding the extra per-item lambda calls and the map overhead). Or just the builtin `Enum._member_names_`. – Trevor Gross Jun 14 '22 at 06:48
  • I think you could rename the `list method to `values` in case other functions are added that return lists. And Q. would changing `@classmethod` to `@staticmethod` be cleaner and closer to the intent? – Carl Aug 05 '22 at 15:48
  • @Carl 1) Yes, `Enum.values` is better. 2) No, `@classmethod` is needed to iterate over the members. – Filip Happy Mar 16 '23 at 11:10
  • This is a clever solution, but not, I think, a good one. It only works for enums that you own and control. – leviathanbadger May 25 '23 at 16:29
  • 1
    Using list comprehension like this: `[e.value for e in Color]` would be better than list of map of lambda – hiru007 Jun 23 '23 at 12:25
104

Use _member_names_ for a quick easy result if it is just the names, i.e.

Color._member_names_

Also, you have _member_map_ which returns an ordered dictionary of the elements. This function returns a collections.OrderedDict, so you have Color._member_map_.items() and Color._member_map_.values() to play with. E.g.

return list(map(lambda x: x.value, Color._member_map_.values()))

will return all the valid values of Color

EliuX
  • 11,389
  • 6
  • 45
  • 40
  • 20
    Underrated answer. – brandonscript Apr 16 '21 at 16:18
  • 1
    This is the real answer without any additional jargon or third part Enum. Works out of box. – foobar Jul 29 '21 at 10:52
  • 5
    This seems a little dirty though, because it's using the private properties of Enum class. – HosseyNJF Oct 19 '21 at 12:37
  • 3
    @HosseyNJF `_member_names_` is not private, it is just a magic/dunder method. – EliuX Oct 19 '21 at 14:50
  • @EliuX, why did you revert my edit? It seems like you changed it back yourself anyway... – BoZenKhaa Nov 23 '21 at 17:19
  • Sorry, I reverted it by mistake and then I reapplied the change. Sorry about that. – EliuX Nov 23 '21 at 20:39
  • 14
    @EliuX Doesn't the leading underscore indicate a non-public value per PEP 8? It's also [not documented](https://docs.python.org/3/library/enum.html). – Antrikshy Feb 18 '22 at 01:17
  • @Antrikshy dunders are a way of Python to avoid conflicts with functions/variables defined by the user, specially with possible Python updates. They are not meant to be public, so they should compete for your attention in your IDE with those who really are public, but they are there to be used in cases like this. – EliuX Apr 20 '22 at 15:45
  • 1
    Sure. I’d just be slightly concerned about having to worry about it when upgrading Python. Since it isn’t documented, there’s a possibility it could be missing in the changelog and migration notes. As long as you have good tests… ¯\\_(ツ)_/¯ – Antrikshy Apr 22 '22 at 02:35
  • About the notation of `_member_names_`, the factory function [collections.namedtuple](https://docs.python.org/3/library/collections.html#collections.namedtuple) is a quintessential example of look-like-private-but-are-production-safe underscored attributes/methods (e.g. `_asdict` etc.) in order to avoid confusion with the user defined attributes —I always trip on `pandas.DataFrame.name`, `pandas.DataFrame.rank` etc. were this does not happen... – Matteo Ferla Sep 21 '22 at 09:35
  • @brandonscript overrated answer. I don't think it's a good idea to rely on _private_ methods or fields. The custom base-enum is much cleaner and safer. – t3chb0t Mar 24 '23 at 19:58
  • 3
    @t3chb0t Python's decision to make it a `_` (private, but not private internal) was a choice to say "don't use this unless you know what you're doing". If they didn't want us using private methods, they should have made them `__` or maybe Python should have actual method privacy – brandonscript Mar 25 '23 at 05:23
72

You can use IntEnum:

from enum import IntEnum

class Color(IntEnum):
   RED = 1
   BLUE = 2


print(int(Color.RED))   # prints 1

To get list of the ints:

enum_list = list(map(int, Color))
print(enum_list) # prints [1, 2]
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • You use third party one. But it also says it has intenum – Marcin Apr 07 '15 at 23:52
  • How do i print like [(1,'RED'), (2, 'BLUE')] – user1159517 Apr 08 '15 at 01:11
  • 1
    What about this: `a = [(int(v), str(v)) for v in Color]` and then `print(a)`. – Marcin Apr 08 '15 at 02:37
  • 82
    How about this: `[(color.value, color.name) for color in Color]` – vlad-ardelean Feb 26 '16 at 16:00
  • 3
    @vlad-ardelean's comment is the best and most pythonic. That's idiomatic usage of the Enum type, elegant, and eminently readable – dusktreader Dec 22 '16 at 22:56
  • this does not work for str enums: ```>>> class QuantityUnit(str, Enum): ... bushels = 'bushels' ... pounds = 'pounds' ... tons = 'tons' ... kilograms = 'kilograms' ... metric_tons = 'metric_tons' ... cwt = 'hundredweight' >>> list(map(str, QuantityUnit)) ['QuantityUnit.bushels', 'QuantityUnit.pounds', 'QuantityUnit.tons', 'QuantityUnit.kilograms', 'QuantityUnit.metric_tons', 'QuantityUnit.cwt'] ``` – amohr May 02 '19 at 01:53
  • `[enum_color.value for enum_color in Color]` would achieve exactly that in a pythonic way. – SKYFALL26 Jul 28 '20 at 20:34
  • A better way is just `class Color(int,Enum): ...`. With that, you can do `sorted(Color)` (sort by value) and `Color.RED>2` (treat as number). Additionally... `np.array(Color) (int64 array), np.array(Color, dtype=object), list(Color)` – ldmtwo Jun 01 '22 at 01:54
45

To use Enum with any type of value, try this:
Updated with some improvements... Thanks @Jeff, by your tip!

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 'GREEN'
    BLUE = ('blue', '#0000ff')

    @staticmethod
    def list():
        return list(map(lambda c: c.value, Color))

print(Color.list())

As result:

[1, 'GREEN', ('blue', '#0000ff')]
Jeff
  • 589
  • 4
  • 11
  • 9
    I would use @classmethod instead of @ staticmethod – ISONecroMAn Feb 17 '18 at 18:12
  • 3
    @ISONecroMAn I guess `@classmethod` would require to create instance of `Color` class. That's why `staticmethod` seems to be correct choice here. – Leonid Dashko Dec 01 '18 at 18:22
  • 1
    @LeonidDashko not at all. See my answer. – blueFast Feb 28 '19 at 05:59
  • @LeonidDashko @dangoonfast is correct. You can use `@classmethod` and use `return list(map(lambda c: c.value, cls))` instead. – Riptyde4 Nov 21 '19 at 23:31
  • Trying to improve the speed of this, there are two notes: using `Color.__members__.values()` instead of Color in the `map()` call will give you a 30% boost right away. You can then get a bit more speed by replacing the lambda with `operator.attrgetter('value')`. – Giacomo Lacava Sep 15 '20 at 11:43
  • 4
    If you have so many Enum Values that speed matters more than readability here, there is something else wrong... – Suzana Nov 06 '20 at 14:21
29

Just use:

[e.value for e in Color]

Produces:

[1, 2]

And to get the names, use:

[e.name for e in Color]

Produces:

['RED', 'BLUE']

25

class enum.Enum is a class that solves all your enumeration needs, so you just need to inherit from it, and add your own fields. Then from then on, all you need to do is to just call it's attributes: name & value:

from enum import Enum

class Letter(Enum):
   A = 1
   B = 2
   C = 3

print({i.name: i.value for i in Letter})
# prints {'A': 1, 'B': 2, 'C': 3}
Meysam
  • 596
  • 6
  • 12
18

You can have a SuperEnum like:

from enum import Enum

class SuperEnum(Enum):    
    @classmethod
    def to_dict(cls):
        """Returns a dictionary representation of the enum."""
        return {e.name: e.value for e in cls}
    
    @classmethod
    def keys(cls):
        """Returns a list of all the enum keys."""
        return cls._member_names_
    
    @classmethod
    def values(cls):
        """Returns a list of all the enum values."""
        return list(cls._value2member_map_.keys())

and use it like:

class Roles(SuperEnum):
    ADMIN = 1
    USER = 2
    GUEST = 3

so you can:

Roles.to_dict() # {'ADMIN': 1, 'USER': 2, 'GUEST': 3}
Roles.keys() # ['ADMIN', 'USER', 'GUEST']
Roles.values() # [1, 2, 3]
supermodo
  • 675
  • 6
  • 15
12

Using a classmethod with __members__:

class RoleNames(str, Enum):
    AGENT = "agent"
    USER = "user"
    PRIMARY_USER = "primary_user"
    SUPER_USER = "super_user"
    
    @classmethod
    def list_roles(cls):
        role_names = [member.value for role, member in cls.__members__.items()]
        return role_names
>>> role_names = RoleNames.list_roles()
>>> print(role_names)

or if you have multiple Enum classes and want to abstract the classmethod:

class BaseEnum(Enum):
    @classmethod
    def list_roles(cls):
        role_names = [member.value for role, member in cls.__members__.items()]
        return role_names


class RoleNames(str, BaseEnum):    
    AGENT = "agent"
    USER = "user"
    PRIMARY_USER = "primary_user"
    SUPER_USER = "super_user"
    

class PermissionNames(str, BaseEnum):
    READ = "updated_at"
    WRITE = "sort_by"
    READ_WRITE = "sort_order"

bwl1289
  • 1,655
  • 1
  • 12
  • 10
10

So the Enum has a __members__ dict. The solution that @ozgur proposed is really the best, but you can do this, which does the same thing, with more work

[color.value for color_name, color in Color.__members__.items()]

The __members__ dictionary could come in handy if you wanted to insert stuff dynamically in it... in some crazy situation.

[EDIT] Apparently __members__ is not a dictionary, but a map proxy. Which means you can't easily add items to it.

You can however do weird stuff like MyEnum.__dict__['_member_map_']['new_key'] = 'new_value', and then you can use the new key like MyEnum.new_key.... but this is just an implementation detail, and should not be played with. Black magic is payed for with huge maintenance costs.

vlad-ardelean
  • 7,480
  • 15
  • 80
  • 124
  • Just a sidebar: can items be added to `__members__`? It would an interesting way to allow *extensions* thereby creating new `Enum` members. ... btw, upvoted for bringing a new (*to me*) attribute to the table. – IAbstract Feb 26 '16 at 17:34
  • @IAbstract: No, that is disallowed. If someone does figure out a way to add/subtract members after the Enum is created they will probably break that Enum. – Ethan Furman Mar 09 '16 at 09:10
  • @IAbstract: Add new members after the fact is not usually a good idea. If you really want to, check out [this answer](http://stackoverflow.com/a/35899963/208880). – Ethan Furman Apr 13 '16 at 18:50
7

One way is to get the keys of the _value2member_map_ property:

class Color(Enum):
    RED = 1
    BLUE = 2

list(Color._value2member_map_.keys())
# [1, 2]
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
6

Given an enum based on the standard python3 Enum/IntEnum classes:

from enum import IntEnum

class LogLevel(IntEnum):
    DEBUG = 0
    INFO = 1
    WARNING = 2
    ERROR = 3

one can do the following to get a list of enum constants:

>>> print(list(LogLevel))
[<LogLevel.DEBUG: 0>, <LogLevel.INFO: 1>, <LogLevel.WARNING: 2>, <LogLevel.ERROR: 3>]

I find it more expressive to work on enum constants instead of ints. If the enum is inheriting from IntEnum, all enum constants are also ints and can used as such everywhere:

>>> level = LogLevel.DEBUG

>>> level == 0
True

>>> level == 1
False

>>> level == LogLevel.INFO
False

>>> level == LogLevel.DEBUG
True

>>> "%d" % level
'0'

>>> "%s" % level
'LogLevel.DEBUG'
derwiwie
  • 875
  • 10
  • 16
2

Here are some examples to easily convert Enum to a list/array of int, str, or Enum AND be able to sort.

import numpy as np

class Color(int,Enum):
    YELLOW = 3
    RED = 1
    BLUE = 2
    
print('1):',list(Color))
print('2):',np.array(list(Color))) ## int64 (8 bytes)
print('3):',sorted(np.array(Color, dtype=str)))
print('4):',np.array(sorted(Color), dtype=object))
print('5):',np.array(sorted(Color), dtype=np.int8)) # 1 byte
print('6):',np.array(sorted(Color, key=lambda x: -x.value), dtype=np.int8))
print('7):',np.array(sorted(Color, key=lambda x: str(x)), dtype=np.int8))

class Color(tuple,Enum):
    YELLOW = (3,3)
    RED = (1,1)
    BLUE = (2,2)
    
print('8):',np.array(sorted(Color)))
print('9):',list(map(tuple,sorted(Color, key=lambda x: -x[1]))))

Output:

1): [<Color.YELLOW: 3>, <Color.RED: 1>, <Color.BLUE: 2>]
2): [3 1 2]
3): ['Color.BLUE', 'Color.RED', 'Color.YELLOW']
4): [<Color.RED: 1> <Color.BLUE: 2> <Color.YELLOW: 3>]
5): [1 2 3]
6): [3 2 1]
7): [2 1 3]
8): [[1 1]
 [2 2]
 [3 3]]
9): [(3, 3), (2, 2), (1, 1)]
ldmtwo
  • 419
  • 5
  • 14
2

if you are using StrEnum or IntEnum, just use the built-in star expression to unpack:

from enum import IntEnum
class Color(IntEnum):
    RED = 0
    GREEN = 1
colors = [*Color]
Hayden
  • 21
  • 4
0

I believe an important comment on some of the answers above is to avoid naming a class method with the python builtin "list"

based on that: https://github.com/encode/django-rest-framework/issues/5884

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34544072) – Robert Jun 20 '23 at 22:43
0

Im gonna throw another option into the mix.

If you don't want to refactor your current code with a different base class to all enums (like the inheritance answers in this thread), you can create a mixin class and just add it to the enums that need that functionality like so:

class ListValsMixIn:

    @classmethod
    def list(cls):
        return list(map(lambda c: c.value, cls))

class Color(ListValsMixIn, Enum):
    RED = 1
    BLUE = 2

print(Color.list())
NotSoShabby
  • 3,316
  • 9
  • 32
  • 56
0

An alternative form of the SuperEnum suggested by @supermodo, which allows iterating over the key-value pairs, and has less magic:

class SuperEnum(IntEnum):

    @classmethod
    def to_dict(cls):
        return {e.name: e.value for e in cls}

    @classmethod
    def items(cls):
        return [(e.name, e.value) for e in cls]

    @classmethod
    def keys(cls):
        return [e.name for e in cls]

    @classmethod
    def values(cls):
        return [e.value for e in cls]

Used like this:

class Roles(SuperEnum):
    ADMIN = 1
    USER = 2
    GUEST = 3

Allows you to do:

Roles.keys()  # ['ADMIN', 'USER', 'GUEST']
Roles.values()  # [1, 2, 3]
Roles.to_dict()  # {'ADMIN': 1, 'USER': 2, 'GUEST': 3}
for key, val in Roles.items():
    print(f"{key} > {val}")  # ADMIN -> 1, etc.

Generators (optimization)

Note that if you prefer generators over lists as return values for items(), keys() and values() then use round braces () instead of square brackets [], e.g.

    @classmethod
    def items(cls):
        return ((e.name, e.value) for e in cls)

    @classmethod
    def keys(cls):
        return (e.name for e in cls)

    @classmethod
    def values(cls):
        return (e.value for e in cls)

Generators are more memory-efficient and often preferred in the Python 3 standard library. The downside of them is that you need to convert them to lists to see the complete result (e.g. when working with them interactively), e.g.

Roles.items()  # <generator object SuperEnum.items.<locals>.<genexpr> at 0x7f3a8c787370>
list(Roles.items())  # [('ADMIN', 1), ('USER', 2), ('GUEST', 3)]
list(Roles.keys())  # ['ADMIN', 'USER', 'GUEST']
list(Roles.values())  # [1, 2, 3]
Peterino
  • 15,097
  • 3
  • 28
  • 29