2017-07-03 58 views
0

访问静态字典我有一个Enum类罗盘方向的如下。 我也有一个在同一类中声明的'对立'字典。在Python 3.6

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 

这是怎么回事,我怎么能解决这个问题pythonically?

回答

2

的基本问题是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成员发生已创建
  • 不允许转发引用

因此,要获得一个干净的(er)实现和API,我们必须后处理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 
+0

这是太酷了。我从这个答案中学到了比过去几天更多的Python。 – Konchog

+1

@Konchog:好评!谢谢! –

1

@RomanPerekhrest得到了信贷这种纯粹由于响应速度,但它采取了一些更扯皮得到我想要的东西,这是从类枚举。如果错误的输入投入它投给枚举本身引发错误..

类文件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的回应是美丽的,其实我实施了,不是说我完全理解它尚未...

1

您的自定义类CompassEnum类,这是枚举衍生而来,但不是可自定义的序列。当你希望它输出<class 'str'>

print(type(Compass.N)) 

- 它输出:

考虑这条线

<enum 'Compass'> 

要访问enumaration对象属性使用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"