在 Python 3.6 中访问静态字典

accessing a static dict in Python 3.6

我有一个罗盘方向的枚举 class,如下所示。 我还有一个 'opposites' dict 在同一个 class 中声明。

from enum import Enum

class Compass(Enum):
    N = 'N'  # North
    S = 'S'  # South
    E = 'E'  # East
    W = 'W'  # West
    opposites = {N: S, S: N, E: W, W: E}

    # static method to provide the opposite values.
    @staticmethod
    def other(com):
        return opposites[com]

当我试图打电话给其他人时,例如。 Compass.other(Compass.N),我希望得到 Compass.S,但我却得到了..

TypeError: 'Com' object is not subscriptable

这是怎么回事,我该如何用 Python 方式解决这个问题?

@RomanPerekhrest 纯粹是因为响应速度而获得荣誉,但我需要更多的争论才能得到我想要的东西,这是 class 中的枚举。如果向 Enum 中输入了错误的输入,则对 Enum 本身的转换会引发错误..

对我有用的 class 文件 folloeinh RomanPerekhrest 看起来像这样。

from enum import Enum

class Compass(Enum):
    N = 'N'  # North
    S = 'S'  # South
    E = 'E'  # East
    W = 'W'  # West
    _opposites = {N: S, S: N, E: W, W: E}

    @staticmethod
    def other(item):
        return Compass(Compass._opposites.value[item.value])

if __name__ == "__main__":
    print(Compass.other(Compass.E))

不过,@EthanFurman 的回复很漂亮,我确实实现了,但我还没有完全理解...

您的自定义 class Compass 派生自 Enum class 这是 枚举 但不是可订阅序列。

考虑这一行:

print(type(Compass.N))

虽然你期望它输出 <class 'str'> - 它输出:

<enum 'Compass'>

访问枚举对象属性使用value属性。

print(Compass.N.value)           # prints "N"
print(Compass.opposites.value)   # prints {'S': 'N', 'N': 'S', 'E': 'W', 'W': 'E'}

正确的 Compass.other() 函数声明应如下所示:

    # static method to provide the opposite values.
    @staticmethod
    def other(item):
        if item in Compass.opposites.value:
            return Compass.opposites.value[item]
        else:
            raise AttributeError('unknown compass direction :', item)

用法:

print(Compass.other(Compass.N.value))  # prints "S"

基本问题是 opposite 正在转变为 Enum 成员,就像 NS,E 和 W 一样。下一个问题是 opposite 中的值——它们 而不是 被转换为 Enum 成员。

理想情况下,我们会有这样的东西:

# NB: does not currently work!

class Compass(Enum):
    N = 'N', S
    S = 'S', N
    E = 'E', W
    W = 'W', E

Compass.E.opposite is Compass.W  # True

这目前不起作用的原因有两个:

  • 从普通值到 Enum 成员的最终转换发生在 class 创建之后
  • 不允许转发引用

因此,为了获得干净的(呃)实现和 API 我们必须 post- 处理 Enum。我会使用装饰器:

class reverse():
    "decorator to add reverse lookups to Enum members"

    def __init__(self, reverse_map):
        "initialize decorator by saving map"
        self.reverse_map = reverse_map

    def __call__(self, enum):
        "apply map to newly created Enum"
        for first, second in self.reverse_map.items():
            enum[first].opposite = enum[second]
            enum[second].opposite = enum[first]
        # don't forget to return the now-decorated Enum
        return enum

并在使用中:

@reverse({'N':'S', 'E':'W'})
class Compass(Enum):
    N = 'N'  # North
    S = 'S'  # South
    E = 'E'  # East
    W = 'W'  # West

>>> Compass.N.opposite is Compass.S
True