【问题标题】:Get complex enum by property in python 3+在python 3+中按属性获取复杂枚举
【发布时间】:2017-02-20 07:06:48
【问题描述】:

我有复杂的 python enum,如下所示:

from enum import Enum

class Properties:
    def __init__(self, name, v, k):
        self.name = name
        self.v = v
        self.k = k


class EnzymeNames(Enum):
    ENZYME_X = Properties("x", 0.2, 50)
    ENZYME_Y = Properties("y", 1.5, 100)

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

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

    def __str__(self):
        return self.value.name

现在,我有一个特殊的功能可以通过它的名字获取enum

def get_enzyme(name) -> EnzymeNames:
    for e in EnzymeNames:
        if str(e) == name:
            return e

我想知道是否有任何简单/pythonic 的方式可以通过EnzymeNames('name') 或类似方式访问enum

编辑

我认为对于我想要实现的目标几乎没有混淆。我想按属性获取 EnzymeNames。例如,EnzymeNames('x') 应该给我 EnzymeNames.ENZYME_X

我已经尝试过以下方法:

>>EnzymeNames('x')
ValueError: 'x' is not a valid EnzymeNames
>>EnzymeNames('ENZYME_X') 
ValueError: 'ENZYME_X' is not a valid EnzymeNames
>>EnzymeNames['ENZYME_X']
KeyError: 'ENZYME_X' 

【问题讨论】:

  • 你可以做EnzymeNames["ENZYME_X"]
  • 另外,由于XY 没有EnzymeNames 就毫无意义,即它们不能不受约束地使用,我不会有那些额外的前缀,而是更喜欢Enzyme.X
  • @SelçukCihan:我已经试过了。它给了我ValueError: 'ENZYME_X' is not a valid EnzymeNames
  • @AnttiHaapala:如果我尝试在不使用属性函数的情况下访问它们,我会收到错误 AttributeError: 'EnzymeNames' object has no attribute 'X'

标签: python python-3.x enums


【解决方案1】:

您使用的是哪个enum?在 Python 3.6、3.5、3.4、3.3 和 2.7 上测试您的代码(对 2.7 和 3.3 使用 enum34 backport)我明白了:

>>> EnzymeNames['ENZYME_X']
x

换句话说:使用内置的Enumenum34 反向移植,您的代码就可以正常工作。


编写枚举的更好方法是将Properties 集成到其中:

from enum import Enum

class Properties:
    def __init__(self, v, k):
        self.v = v
        self.k = k


class EnzymeNames(Properties, Enum):

    X = 0.2, 50
    Y = 1.5, 100

    def __str__(self):
        return self.name

并在使用中:

>>> print(EnzymeNames.X)
X

>>> print(EnzymeNames.X.name)
X

>>> print(EnzymeNames.X.v)
0.2

>>> print(EnzymeNames.X.k)
50

>>> print(EnzymeNames['X'])
X

enums的一些一般技巧:

  • 保持名称单数; EnzymeName 而不是 EnzymeNames
  • 不要在枚举成员中重复枚举名称:X 而不是ENZYME_X
  • 如果您使用Enum 做一些花哨的事情,请考虑使用Advanced Enum library(与Enumenum34 由同一作者撰写)

使用aenum,您的代码可能如下所示:

from aenum import Enum

class EnzymeName(Enum, init='v k'):

    X = 0.2, 50
    Y = 1.5, 100

    def __str__(self):
        return self.name

【讨论】:

    【解决方案2】:

    我建议稍微重组您的代码以使用namedtuples。它们是轻量级的,易于创建像enums 这样的不可变对象。请参阅this post 以获得更好的解释,而不是我可以将它们放在一起。

    这是您的代码,其中添加了两个方法来通过Properties 属性值检索实例。

    代码:

    from enum import Enum
    import collections
    import math
    
    Properties = collections.namedtuple('Properties', 'v k')
    
    class EnzymeNames(Enum):
        x = Properties(0.2, 50)
        y = Properties(1.5, 100)
    
        @property
        def v(self):
            return self.value.v
    
        @property
        def k(self):
            return self.value.k
    
        @classmethod
        def from_v(cls, v):
            for en in cls:
                if math.isclose(en.v, v):
                    return en
    
        @classmethod
        def from_k(cls, k):
            for en in cls:
                if math.isclose(en.k, k):
                    return en
    

    测试代码:

    an_enzyme = EnzymeNames.from_k(100)
    print(an_enzyme)
    print('name:', an_enzyme.name)
    print('k:', an_enzyme.k)
    print('v:', an_enzyme.v)
    

    输出:

    EnzymeNames.y
    name: y
    k: 100
    v: 1.5
    

    【讨论】:

    • 嗨,你能解释一下namedtuple部分吗?
    猜你喜欢
    • 2011-02-16
    • 2023-04-04
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    • 2010-12-20
    相关资源
    最近更新 更多