Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a self-referential Python 3 Enum?

Can I create an enum class RockPaperScissors such that ROCK.value == "rock" and ROCK.beats == SCISSORS, where ROCK and SCISSORS are both constants in RockPaperScissors?

like image 391
l0b0 Avatar asked Jun 04 '19 04:06

l0b0


People also ask

What is enum Auto ()?

Syntax : enum.auto() Automatically assign the integer value to the values of enum class attributes. Example #1 : In this example we can see that by using enum. auto() method, we are able to assign the numerical values automatically to the class attributes by using this method.

Can enum have multiple values Python?

Enums can't have multiple value per name.

Can we use enum in Python?

Enum is a class in python for creating enumerations, which are a set of symbolic names (members) bound to unique, constant values. The members of an enumeration can be compared by these symbolic anmes, and the enumeration itself can be iterated over. An enum has the following characteristics.


2 Answers

Having Enum members refer to each other during class creation is a bit tricky; the trick is knowing that each member is created and initialized before it is added to the Enum itself. This means you can examine the state of the Enum you are creating and make adjustments to both the member-being-created as well as members-already-created.

The basic problem here is making circular references between the members, and we can solve that by modifying the circle with each new member:

class RPS(Enum):

    Rock = "rock"
    Paper = "paper"
    Scissors = "scissors"

    def __init__(self, value):
        if len(self.__class__):
            # make links
            all = list(self.__class__)
            first, previous = all[0], all[-1]
            first.beats = self
            self.beats = previous

and in use:

>>> print(RPS.Rock.beats)
RPS.Scissors

>>> print(RPS.Paper.beats)
RPS.Rock

>>> print(RPS.Scissors.beats)
RPS.Paper

Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

like image 167
Ethan Furman Avatar answered Oct 20 '22 07:10

Ethan Furman


By picking the order of the members carefully, each member can simply be described as beating the previous with a property.

from enum import Enum

class RPS(Enum):
    Rock = 0
    Paper = 1
    Scissor = 2

    @property
    def beats(self):
        return list(RPS)[self.value - 1]

for v in RPS:
    print(v.name, 'beats', v.beats.name)

Output

Rock beats Scissor
Paper beats Rock
Scissor beats Paper
like image 42
Olivier Melançon Avatar answered Oct 20 '22 05:10

Olivier Melançon