【问题标题】:Enum with infinite/dynamic members具有无限/动态成员的枚举
【发布时间】:2021-04-17 16:49:56
【问题描述】:

摘要:我想要一个(整数)枚举,其中包含一些(负)成员,这些成员对应于特定状态和未绑定(正)成员。

示例:假设我们有一个数据库条目,其中存储了比赛中的获胜位置。如果比赛结束,这些条目是积极的。但是,也有一些特殊值,例如没有完成没有参加失格。这些以负值的形式存储在数据库中。

现在我想用 Python 来表示这个结构。由于枚举是不可变的,因此这变得相当困难。我已经研究了enum.EnumMeta 并查看了aenum 库,但没有找到解决方案。我最不荒谬的想法是有一个像下面这样的枚举:

import enum

class RankingPlace(enum.IntEnum):
    FINISHED = 0
    DID_NOT_FINISH = -1
    DID_NOT_ATTEND = -2
    DISQUALIFIED = -3

    def __call__(self, value):
        if value < 0:
            return super()(member)
        else:
            member = self.__class__.FINISHED
            member.actual_place = value
            return member

这有点工作,但我必须打电话给一个成员才能让它工作。有没有更清洁的方法使用例如自定义元类?

【问题讨论】:

  • 如果枚举不限于这些特定值,它似乎是错误的。只需为特殊值声明变量。
  • 请注意enum 的意义在于创建enumerated types——这意味着具有可枚举(固定数量)值的类型。允许任意数量的成员违背了目的。

标签: python enums metaclass


【解决方案1】:

听起来最好的解决方案是Enum 和其他东西的组合——也许是namedtuple(使用NamedTuple 的示例代码来自aenum

class Status(aenum.IntEnum):
    FINISHED = 0
    DID_NOT_FINISH = -1
    DID_NOT_ATTEND = -2
    DISQUALIFIED = -3

class Placement(aenum.NamedTuple):
    race = 0, 'name of race'
    status = 1, 'finished race?'
    placement = 2, 'position when finished'

winner = Placement('2021 Marathon', Status.FINISHED, 1)

【讨论】:

    【解决方案2】:

    我已经考虑过元组,但想将所有内容都保存在一个类中,因为我必须为多个枚举执行此操作,并且不希望每个枚举都有两个类。这部分是由于我们在应用程序中使用的运行时验证机制并试图保持代码 DRY。

    但是阅读@Ethan 的回答和上面的 cmets,我想出了一个聪明的解决方案(或者我认为),它仍然允许 mypy 正确检查类型。

    from enum import IntEnum
    from typing import Generic, TypeVar
    
    E = TypeVar("E", bound=IntEnum)
    
    # use Generic as mypy does not support generic NamedTuple yet
    class InfiniteEnum(Generic[E]):
        def __init__(self, enum: E, int_: int):
            self.enum = enum
            self.int = int_
    
    class Status(IntEnum):
        FINISHED = 0
        DID_NOT_FINISH = -1
        DID_NOT_ATTEND = -2
        DISQUALIFIED = -3
    
    winner = InfiniteEnum[Status](Status.FINISHED, 1)
    

    如果只有在我接受的答案更清晰时才需要这个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      相关资源
      最近更新 更多