首页 > 解决方案 > Adding a property to an Enum

问题描述

I would like to have an Enum with internal property for each enum value, this property can't be set or initialized by the user, but once the user has created Enum from a value, he would be able to read (get) this internal property based on the value.

e.g.

class Channels(Enum):

    Email     = 1, True   # True is the value of the internal property for value 1
    Sms       = 2, True   # True is the value of the internal property for value 2
    Log       = 3, False  # False is the value of the internal property for value 3

Problem is that currently in order to create an instance of this class I need to: x = Channels((1, True)) and that's bad. I want to be able to still create instances like: x = Channels(1) (i.e. True is the internal property of 1, it shouldn't be specified by the user).

My second try was:

class Channels2(Enum):

    @DynamicClassAttribute
    def internal_property(self):
        if self.value == 1:
            return True
        elif self.value == 2:
            return True
        elif self.value == 3:
            return False


    Email     = 1
    Sms       = 2
    Log       = 3

And this seems to be working (x = Channels(1) is working and x.internal_property returns True, as it should).

The problem here is that it feels not so efficient, executing those if statements every time the internal_property is accessed.. Is there any other way making the Enum treat internal_property as a an extra field of the instance (on top of Enum regular name and value fields)?

标签: pythonpython-3.xenumsproperties

解决方案


您可以使用__new__()此处记录的方法来自定义枚举对象的值。例如,您可以使用原始定义,例如:

from enum import Enum

class Channels(Enum):

    def __new__(cls, value, internal_property):
        obj = object.__new__(cls)
        obj._value_ = value
        obj.internal_property = internal_property
        return obj

    email = 1, True
    sms   = 2, True
    log   = 3, False

print(Channels.email)
# Coordinate.email

print(Channels.email.value)
# 1

print(Channels(3))
# Coordinate.log

print(Channels(3).internal_property)
# False

print(Channels(1).internal_property)
#True

推荐阅读