Is there a way to specify a default value for python enums?

Viewed 19945

Given the following enum:

class MyEnum(IntEnum):

    A = 0
    B = 1
    C = 2

How can I specify a default value. I want to be able to do:

my_val = MyEnum()

and havemy_val be <MyEnum.A: 0>

Is this possible? I've tried customizing __new__, __init__, __call__ but I can't get it to work.

5 Answers

falsetru's answer would be the way to go if 0 argument case needs to be catered.

If it is only about returning default when given value does not exist, we can override _missing_ hook in Enum class (Since Python 3.6):

from enum import IntEnum


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

    @classmethod
    def _missing_(cls, value):
        return cls.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

I also stumbled upon this problem. Posting my solution for Python 3.9.5

from enum import unique, Enum, EnumMeta

class PrinterModelMeta(EnumMeta):
    def __call__(cls, value=-1, *args, **kwargs):
        if value == -1:
            value = PrinterModel.detect_model()
        return super().__call__(value, *args, **kwargs)


@unique
class PrinterModel(Enum, metaclass=PrinterModelMeta):
    # FORBIDDEN = -1
    MODEL0 = 0
    MODEL1 = 1
    MODEL2 = 2

    @classmethod
    def detect_model(cls) -> int:
        model = None
        panel_name = cls.panel_name()
        if panel_name == "model-aaa":
            model = PrinterModel.MODEL0
        if panel_name == "model-bbb":
            model = PrinterModel.MODEL1
        if panel_name == "model-ccc":
            model = PrinterModel.MODEL2

        logger = logging.getLogger(__name__)
        if model is None:
            raise UnknownPrinterModel()
        else:
            return model.value

    @classmethod
    def panel_name(cls) -> str:
        path = Path("/sys/bus/i2c/devices/1-000f/of_node") / "panel-name"
        return path.read_text()[:-1] if path.exists() else None
Related