如何在Python中表示枚举

如何在Python中表示枚举,python,enums,Python,Enums,我知道,我知道,在和中已经有类似的问题。但他们的问题和答案并不是我想要的。此外,它们是一个被锁定的问题,所以我不能为它们添加新的答案。SMH 首先,让我们澄清问题,了解其范围。在其他静态语言中使用enum时,如下所示: public enum Size { SMALL=0, MIDIUM=1, LARGE=2, BIG=2 // There can possibly be an alias } 我们希望它能帮助我们: 在引用值时要防止输入错误。例如,var f

我知道,我知道,在和中已经有类似的问题。但他们的问题和答案并不是我想要的。此外,它们是一个被锁定的问题,所以我不能为它们添加新的答案。SMH

首先,让我们澄清问题,了解其范围。在其他静态语言中使用enum时,如下所示:

public enum Size
{
    SMALL=0,
    MIDIUM=1,
    LARGE=2,
    BIG=2  // There can possibly be an alias
}
我们希望它能帮助我们:

  • 在引用值时要防止输入错误。例如,
    var foo=Size.SMALL
    是有效的,
    var bar=Size.SMAL
    应该会生成一个糟糕的错误
  • 枚举值可以支持字符串,例如
    HTTP404=“未找到”、HTTP200=“确定”、…
    。(因此,基于
    范围(N)
    的实现是不可接受的。)
  • 将参数定义为特定枚举类型时,它作为一种规则,只接受该类型的值。例如,
    publicvoidfoo(大小){…}
  • 我还希望这些值在我的枚举解决方案中是一等公民。也就是说,我的函数
    def parser(value\u来自\u线路):…
    希望使用一些本机值(例如整数或字符串等),而不是使用Enum成员。这是Python 3中标准枚举的棘手部分:

    • assert 2==MY_ENUM。只有当MY_ENUM从
      IntEnum
      派生时,MY_值才会起作用(并且没有默认的
      strengum
      ,尽管自己对一个进行子类化并不困难)
    • 在MY_ENUM中断言2
      不起作用,即使MY_ENUM是从
      IntEnum
      派生的

  • TL;DR:使用

    因此,我的Python解决方案以满足问题中的3个标准为基础,其实现似乎比新的更简单

    使用现在很简单

    # definition syntax
    SIZE = enum("Size", SMALL=0, MEDIUM=1, LARGE=2, BIG=2)
    
    # usage on referencing
    print(SIZE.SMALL)   # got 0, instead of <SIZE.SMALL: 0>
    try:
        print(SIZE.SMAL)    # got AttributeError
        assert False, "should not arrive this line"
    except AttributeError:
        pass
    
    # usage on comparison and contains-check
    assert SIZE.MEDIUM == 1  # works. It won't work when using standard Enum (unless using IntEnum)
    assert 1 in SIZE  # works. It won't work when using standard Enum (unless you wrote it as SIZE(1)).
    
    # usage on regulating input value
    def t_shirt_size(size):
    
        if size not in SIZE:
            raise ValueError("Invalid input value")
    
        print("Placing order with size: %s" % size)
    
    t_shirt_size(SIZE.MEDIUM)   # works
    t_shirt_size(2)             # also want this to work
    try:
        t_shirt_size(7)             # got AssertionError
        assert False, "This line should not be reached!"
    except ValueError:
        pass
    
    定义语法 大小=枚举(“大小”,小=0,中=1,大=2,大=2) #引用的用法 打印(大小。小)#得到0,而不是 尝试: 打印(SIZE.SMAL)#属性错误 断言False,“不应到达此行” 除属性错误外: 通过 #比较和包含检查的用法 assert SIZE.MEDIUM==1#有效。使用标准枚举时,它将不起作用(除非使用IntEnum) 断言1在大小上有效。当使用标准枚举时,它将不起作用(除非您将其写成大小(1))。 #调节输入值的用法 def t恤衫尺寸(尺码): 如果大小不一致: 提升值错误(“无效输入值”) 打印(“下订单大小:%s”%size) t恤衫尺码(中号)#合适 t恤衫(2号)#也希望它能起作用 尝试: t恤衫尺码(7号)#有断言错误 断言False,“不应到达此行!” 除值错误外: 通过
    编辑1:我实际上意识到,在功能方面,有一个主要是我下面的一行程序实现的超集。但是,有一种情况是,标准枚举不能满足我的需要。我希望这些值在我的枚举中是一等公民;我希望我的
    t\u shirt\u size(…)
    函数接受实际值,而不仅仅是枚举成员。标准枚举方法不允许以下两种用法:
    assert SIZE.MEDIUM==1
    assert 1 in SIZE


    编辑2:考虑到人们倾向于将这个主题定型为重复的主题,我计划将我的方法实际实现为一个独立的模块,包含大量的文档。我甚至给它起了一个很酷的名字,
    venum
    ,V代表价值。就是在那个时候,我在pypi中检查了这个名称,发现已经有一个同名的包,使用与我相同的方法,并且。就这样解决了。我只想改为::-)

    使用Python 3的
    Enum
    实现:

    from enum import IntEnum
    
    
    class SIZE(Enum):
    
        SMALL = 0
        MEDIUM = 1
        LARGE = 2
        BIG = 2
    
        @classmethod
        def contains(cls, value):
            return any([e.value == value for e in cls])
    
    并使用:

    print(SIZE.SMALL)   # got <SIZE.SMALL: 0>
    print(SIZE.SMAL)    # got AttributeError
    
    def t_shirt_size(size):
        assert size in SIZE, "Invalid input value"
        place_order_with_size(size)
    
    t_shirt_size(SIZE.MEDIUM)   # works
    t_shirt_size(7)             # got AssertionError
    
    打印(大小.小)#得到
    打印(SIZE.SMAL)#属性错误
    def t恤衫尺寸(尺码):
    在大小中断言大小,“输入值无效”
    使用尺寸(尺寸)下订单
    t恤衫尺码(中号)#合适
    t恤衫尺码(7号)#有断言错误
    
    我不明白您的问题与您链接的问题有何不同。为什么那里的答案不能回答你的问题?@Aran Fey这些问题都没有阐明要求,因此,他们的答案往往基于不同回答者心中的不同假设。嗯?有什么需要澄清的?我认为,“如何表示枚举”这个问题相当清楚。你的枚举能做什么,而现有答案中的其他枚举却做不到?好吧,当我发布这个问答时,至少我做了我的家庭作业。你在发表评论之前做过自己的评论吗?大多数简单的解决方案
    类MY_ENUM:NAME1=“value1”
    不满足我的要求#3,即允许在MY_ENUM中输入
    if值:…
    检查。其他一些人有一个假设“如果你需要数值,这里是最快的方法:
    dog,cat,rabbit=range(3)
    ”,这不是我想要的。你是认真的吗?你列出的所有问题都与这个问题无关。只有当您选择了一种不好的方式来表示枚举时,这些问题才会存在。所有这些都是答案的问题,而不是问题。如果你看到一个糟糕的答案,就投反对票。你的问题和另一个问题没有什么不同。谢谢你的否决票。实际上,我知道在Python3中有一个标准的
    Enum
    模块,从功能上讲,它主要是我的单行程序实现的超集。然而,有一种情况是它不适合我的需要。我希望这些值在我的枚举中是一等公民;我希望我的
    t\u shirt\u size(…)
    函数接受实际值,而不仅仅是枚举成员。标准枚举方法不允许以下两种用法:
    assert SIZE.MEDIUM==1
    assert 1 in SIZE
    。现在,你的具体回答不符合我的需要。但我不会投反对票。你也公平吗?@raylou:
    assert SIZE.MEDIUM==1
    IntEnum一起工作
    
    print(SIZE.SMALL)   # got <SIZE.SMALL: 0>
    print(SIZE.SMAL)    # got AttributeError
    
    def t_shirt_size(size):
        assert size in SIZE, "Invalid input value"
        place_order_with_size(size)
    
    t_shirt_size(SIZE.MEDIUM)   # works
    t_shirt_size(7)             # got AssertionError