有没有办法为python枚举指定默认值?

Ste*_*hen 3 python enums

鉴于以下枚举:

class MyEnum(IntEnum):

    A = 0
    B = 1
    C = 2
Run Code Online (Sandbox Code Playgroud)

如何指定默认值.我希望能够做到:

my_val = MyEnum()
Run Code Online (Sandbox Code Playgroud)

并具有my_val<MyEnum.A: 0>

这可能吗?我试过定制__new__,__init__,__call__但我不能得到它的工作.

Cha*_*Lin 21

如果需要满足 0 个参数的情况,falsetru 的答案将是可行的方法。

如果只是在给定值不存在时返回默认值,我们可以覆盖_missing_Enum 类中的钩子(自Python 3.6 起):

from enum import IntEnum


class MyEnum(IntEnum):
    A = 0
    B = 1
    C = 2

    @classmethod
    def _missing_(cls, value):
        return MyEnum.A

assert MyEnum(0) is MyEnum.A
assert MyEnum(1) is MyEnum.B
assert MyEnum(-1) is MyEnum.A
assert MyEnum(None) is MyEnum.A
Run Code Online (Sandbox Code Playgroud)

  • 感谢您提到“_missing_”方法。不幸的是,这并不能解决问题。`MyEnum()` 仍然会导致 `TypeError`。目标是能够在*不*提供参数的情况下创建“MyEnum”的实例。 (3认同)

fal*_*tru 6

MyEnum(..)由...处理EnumMeta.__call__.您需要覆盖该方法:

from enum import EnumMeta, IntEnum


class DefaultEnumMeta(EnumMeta):
    default = object()

    def __call__(cls, value=default, *args, **kwargs):
        if value is DefaultEnumMeta.default:
            # Assume the first enum is default
            return next(iter(cls))
        return super().__call__(value, *args, **kwargs)
        # return super(DefaultEnumMeta, cls).__call__(value, *args, **kwargs) # PY2


class MyEnum(IntEnum, metaclass=DefaultEnumMeta):
    # __metaclass__ = DefaultEnumMeta  # PY2 with enum34
    A = 0
    B = 1
    C = 2


assert MyEnum() is MyEnum.A
assert MyEnum(0) is MyEnum.A
assert MyEnum(1) is not MyEnum.A
Run Code Online (Sandbox Code Playgroud)

  • 对于这样一个简单的问题来说,这似乎是严重的矫枉过正。 (3认同)
  • @EthanFurman,是的,确实如此。但我无法想出一个满足“MyEnum() is MyEnum.A”的解决方案 (2认同)

Eth*_*man 6

更新

aenum 2.2.11 开始,支持不带值调用 Enum:

from aenum import Enum, no_arg

class Color(Enum):
    black = 0
    red = 1
    green = 2
    blue = 3
    #
    @classmethod
    def _missing_value_(cls, value):
        if value is no_arg:
            return cls.black
Run Code Online (Sandbox Code Playgroud)

并在使用中:

>>> Color(1)
<Color.red: 1>

>>> Color()
<Color.black: 0>

>>> Color(4)
Traceback (most recent call last):
  ...
ValueError: 4 is not a valid Color
Run Code Online (Sandbox Code Playgroud)

原答案

如果您不控制Enums,请执行以下操作:

my_val = list(MyEnum)[0]
Run Code Online (Sandbox Code Playgroud)

或者,如果Enum可能为空:

my_val = len(MyEnum) and list(MyEnum)[0] or None
Run Code Online (Sandbox Code Playgroud)

如果您确实控制了Enums,则添加一个get_default方法:

class MyEnum(Enum):
    def get_default(self):
        return self.A
Run Code Online (Sandbox Code Playgroud)

或者,甚至更简单, makedefault是一个别名:

class MyEnum(Enum):
    A = 0
    B = 1
    C = 2
    default = A
Run Code Online (Sandbox Code Playgroud)

您还可以将第一个方法包装到一个函数中:

def default_member(enum):
    return list(enum)[0]
Run Code Online (Sandbox Code Playgroud)

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