【问题标题】:How to define custom properties in enumeration in Python (Javascript-like) [duplicate]如何在 Python 中的枚举中定义自定义属性(类似 Javascript)[重复]
【发布时间】:2016-02-23 02:31:58
【问题描述】:

在 JavaScript 中我们可以这样做:

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

所以我可以打电话:

Color.YELLOW.displayString

在 Java 中我们可以这样做:

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;}
}

所以我可以打电话:

Color.YELLOW.getDisplayString()

经过大量研究,我还没有找到使用内置 Enum 模块在 Python 中执行此操作的干净方法。我该怎么做?

谢谢

【问题讨论】:

  • javascript是一个与Java中的HashMap关系更密切的对象。 python 中有一个字典可以满足您的目的。

标签: python python-3.x


【解决方案1】:

这里涉及两个概念:枚举和对可以内联初始化的对象成员的属性样式访问。对于后者,您将需要某种自定义类,但由于您想要一些非常简单的东西,namedtuple 就足够了。所以,结合namedtupleenum,这可能是一个解决方案:

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)

【讨论】:

  • 非常感谢,这正是我所需要的!结合@property 注释的使用,我们可以像这样直接访问底层值:Colors.yellow.displayString
  • 感谢您指出这一点,我已经编辑了答案以进行演示。
  • 如何按值获取枚举对象?它在这里工作吗!
【解决方案2】:

这是另一种方法,代码来自: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'

或基于此代码的东西,但有点短:

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'

【讨论】:

    【解决方案3】:

    您可以使用dictionary in python

    Color = { 
        'YELLOW': { 'value': 1, 'displayString': "Yellow" },
        'GREEN': { 'value': 2, 'displayString': "Green" }
    }
    Color['YELLOW']['displayString']
    

    【讨论】:

      【解决方案4】:

      你通常不应该在你的代码中包含这样的文字。内容应来自文件或数据库。但是你可以看到如何构建它

      >>> from collections import namedtuple
      >>> Color = namedtuple("color", "YELLOW,GREEN")(
              namedtuple("yellow", "value,display_string")(1, "yellow"),
              namedtuple("green", "value,display_string")(2, "green"))
      >>> Color.YELLOW.display_string
      'yellow'
      

      这也适用于不支持枚举的旧版 Python

      【讨论】:

        猜你喜欢
        • 2016-12-11
        • 2016-01-05
        • 1970-01-01
        • 1970-01-01
        • 2017-04-02
        • 1970-01-01
        • 2013-02-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多