Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define custom properties in enumeration in Python (Javascript-like) [duplicate]

In JavaScript we can do this:

var Color = {
    YELLOW: { value: 1, displayString: "Yellow" },
    GREEN: { value: 2, displayString: "Green" },
}

So I can call:

Color.YELLOW.displayString

In Java we can do this:

public enum Color {

    YELLOW (1, "Yellow"),
    GREEN (2, "Green"),

    private Color(String value, int displayString){
        this.value = value;
        this.displayString = displayString;
    }

    private final int value;
    private final String displayString;

    public String getValue() {return value;}
    public String getDisplayString() {return displayString;}
}

So I can call:

Color.YELLOW.getDisplayString()

After much research I haven't found a clean way to do this in Python using the built-in Enum module. How can I do this?

Thanks

like image 342
olivierr91 Avatar asked Feb 23 '16 02:02

olivierr91


People also ask

Can enum have multiple values Python?

Enums can't have multiple value per name.

What is the preferred syntax for defining enums in JavaScript?

The preferred syntax for defining enums in JavaScript is to use the objects see the code below:- var DaysEnum = Object. freeze({"monday":1, "tuesday":2, "wednesday":3, ...})

What is Auto () in Python?

auto() method, we can get the assigned integer value automatically by just using enum. auto() method. Syntax : enum.auto() Automatically assign the integer value to the values of enum class attributes.


2 Answers

There are two concepts involved here: enumerations and attribute-style access to object members that can be initialised inline. For the latter, you'll need some kind of custom class, but since you want something very straightforward, a namedtuple is sufficient for that. So, combining namedtuple and enum, this could be a solution:

from enum import Enum
from collections import namedtuple

Color = namedtuple('Color', ['value', 'displayString'])

class Colors(Enum):

    @property
    def displayString(self):
        return self.value.displayString

    yellow = Color(1, 'Yellow')
    green = Color(2, 'Green')

print(Colors.yellow.displayString)
like image 102
Thomas Lotze Avatar answered Oct 11 '22 07:10

Thomas Lotze


Here is another approach, that is the code from: https://github.com/hzdg/django-enumfields

import enum
import inspect

class ColorEnumMeta(enum.EnumMeta):
    def __new__(mcs, name, bases, attrs):
        DisplayStrings = attrs.get('DisplayStrings')

        if DisplayStrings is not None and inspect.isclass(DisplayStrings):
            del attrs['DisplayStrings']
            if hasattr(attrs, '_member_names'):
                attrs._member_names.remove('DisplayStrings')

        obj = super().__new__(mcs, name, bases, attrs)
        for m in obj:
            m.display_string = getattr(DisplayStrings, m.name, None)

        return obj

class Color(enum.Enum, metaclass=ColorEnumMeta):
    yellow = 1
    green = 2

    class DisplayStrings:
        yellow = 'Yellow'
        green = 'Green'

print(Color.yellow.display_string)  # 'Yellow'

or something that is based on this code, but a bit shorter:

import enum

class ColorEnumMeta(enum.EnumMeta):
    def __new__(mcs, name, bases, attrs):
        obj = super().__new__(mcs, name, bases, attrs)
        obj._value2member_map_ = {}
        for m in obj:
            value, display_string = m.value
            m._value_ = value
            m.display_string = display_string
            obj._value2member_map_[value] = m

        return obj

class Color(enum.Enum, metaclass=ColorEnumMeta):
    yellow = 1, 'Yellow'
    green = 2, 'Green'

print(Color.yellow.display_string)  # 'Yellow'
like image 29
Arany Avatar answered Oct 11 '22 07:10

Arany