2016-11-17 94 views
2

這是Why are mutable values in Python Enums the same object?的後續內容。爲什麼在Python Enums中允許可變值?

如果Enum的值是可變的(例如list等),則可以隨時更改這些值。我想,這提出了一個問題的東西,如果Enum成員由價值獲取,特別是如果有人無意中改變了Enum的價值,他擡頭:

>>> from enum import Enum 
>>> class Color(Enum): 
     black = [1,2] 
     blue = [1,2,3] 

>>> val_1 = [1,2] 
>>> val_2 = [1,2,3] 
>>> Color(val_1) 
<Color.black: [1, 2]> 
>>> Color(val_2) 
<Color.blue: [1, 2, 3]> 
>>> my_color = Color(val_1) 
>>> my_color.value.append(3) 
>>> Color(val_2) 
<Color.black: [1, 2, 3]> 
>>> Color(val_1) 
Traceback (most recent call last): 
    ... 
ValueError: [1, 2] is not a valid Color 

我想給Python的成語,這是沒關係,與這意味着用戶可以使用作爲他們的Enum值,但僅僅是爲了理解它們可能打開的蠕蟲罐。

然而這帶來了第二個問題 - 因爲你可以按值查找一個Enum memeber,和值可以是可變的,它必須比一個HashMap/dict之外的方式做的查找,因爲可變不能在這樣的dict中是key

Enum的值限制爲僅可變類型的效率會不會更高效(雖然授予了靈活性),以便可以使用dict來實現按值查找?

回答

1

看來我的第二個問題的答案隱藏在enum.py的soure代碼中。

Enum每個確實含有value->member一個dict用於對哈希的(即不變的)值,並且當通過值查找一個Enum,它試圖檢索從dict的構件。如果該值不是可排列,則強制比較與所有現有的Enum值相等,如果找到匹配則返回成員。相關的代碼是在線路468-476在enum.py

try: 
    if value in cls._value2member_map_: 
     return cls._value2member_map_[value] 
except TypeError: 
    # not there, now do long search -- O(n) behavior 
    for member in cls._member_map_.values(): 
     if member._value_ == value: 
      return member 
raise ValueError("%r is not a valid %s" % (value, cls.__name__)) 

所以看起來好像的enum.py的設計者希望通過有獲得價值Enum■當,但仍然是一個快速查找想給具有靈活性Enum值的可變值(儘管我仍然無法想到原因爲什麼有人會首先想要這樣做)。

相關問題