【问题标题】:Adding a property to an Enum向枚举添加属性
【发布时间】:2020-05-11 22:56:07
【问题描述】:

我希望每个枚举值都有一个带有内部属性的Enum,这个属性不能由用户设置或初始化,但是一旦用户从一个值创建了Enum,他就可以根据值读取(获取)这个内部属性。

例如

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

问题是,目前为了创建此类的实例,我需要: x = Channels((1, True)) 这很糟糕。我希望仍然能够创建如下实例:x = Channels(1)(即True 是 1 的内部属性,不应由用户指定)。

我的第二次尝试是:

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

这似乎有效(x = Channels(1) 有效,x.internal_property 返回 True,应该如此)。

这里的问题是感觉效率不高,每次访问internal_property 时都执行那些if 语句。有没有其他方法可以使Enuminternal_property 视为实例的额外字段(在Enum 常规namevalue 字段之上)?

【问题讨论】:

    标签: python python-3.x enums properties


    【解决方案1】:

    您可以将__new__() 用作documented here 来自定义枚举对象的值。例如,您可以使用原始定义,例如:

    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
    

    【讨论】:

    • 看起来不错!不过,您不需要从 int 继承 -- 只需执行 obj = object.__new__(cls)
    • 谢谢@EthanFurman——我更新了答案。 aenum 看起来很棒!
    【解决方案2】:

    @MarkMeyer 的stdlib 解决方案很好,但如果您正在寻找更简单的方法来创建Enums,您应该尝试aenum1

    from aenum import Enum
    
    class Channels(Enum):
        #
        _init_ = 'value internal_property'
        #
        email = 1, True
        sms   = 2, True
        log   = 3, False
    

    并在使用中:

    >>> list(Channels)
    [<Channels.email: 1>, <Channels.sms: 2>, <Channels.log: 3>]
    
    >>> Channels(2)
    <Channels.sms: 2>
    
    >>> Channels(2).name
    'sms'
    
    >>> Channels(2).internal_property
    True
    

    1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum) 库的作者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2015-03-24
      • 1970-01-01
      相关资源
      最近更新 更多