2017-07-03 108 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"