1

I wish to know if this is the best way to combine two or more Python Enum classes into a final class that collects each Enum class and to have a more levels.

Consider the example of @EthanFurman in the page Python Enum combination

from enum import Enum, unique
from itertools import chain

@unique
class Letters(Enum):
    A = 'a'
    B = 'b'
    C = 'c'

    def __str__(self):
        return str(self.value)

@unique
class Numbers(Enum):
    ONE = 'one'
    TWO = 'two'
    THREE = 'three'

    def __str__(self):
        return str(self.value)

Etahn Furman suggests the following class of combination:

class CombinedEnum(Enum):
    """ doc string """
    _ignore_ = 'member cls'
    cls = vars()
    for member in chain(list(Letters), list(Numbers)):
        cls[member.name] = member.value

    def __str__(self):
        return str(self.value)


if __name__ == '__main__':
    print(str(CombinedEnum.A))
    print(str(CombinedEnum.B))
    print(str(CombinedEnum.C))
    print(str(CombinedEnum.ONE))
    print(str(CombinedEnum.TWO))
    print(str(CombinedEnum.THREE))

However, the multi-level class I would like to create should access the values in the following way:

CombinedEnum.Letters.A
CombinedEnum.Letters.B
CombinedEnum.Letters.C

CombinedEnum.Numbers.ONE
CombinedEnum.Numbers.TWO
CombinedEnum.Numbers.THREE

Typically, the basic solution I use is to use a composition class where the variables are the various Enum classes.

class World:
    """ doc string """
    LETTERS = Letters
    NUMBERS = Numbers
Gianni Spear
  • 7,033
  • 22
  • 82
  • 131

1 Answers1

0

It depends on how you want to use World and A, B, C, ONE, TWO, and THREE:

  • will you be checking to see if A is an instance of World?
  • do A and ONE need to be part of the same enum?

If the answer to both of those is "no", then your World class is probably fine.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • Hey Ethan thanks for your replay and thanks for your Enum work (I love it!). The choice of composition is not perfect because using my IDE (Pycharm) the "value" method (and "name") is not (e.g. World.NUMBERS.value) hidden causing an exception to be raised if it is inadvertently chosen by the developer. i.e., "raise AttributeError(name) from None AttributeError: value". – Gianni Spear Mar 18 '22 at 18:22
  • @GianniSpear: In your example above, `World` is not an enum, so `World.NUMBERS.value` *is* an error. – Ethan Furman May 10 '22 at 22:25
  • hey Ethan, World is a composition class. I did not figure out a way to make a composition of enum class – Gianni Spear May 11 '22 at 12:50