Вам необходимо переопределить методы __setitem__
и __getitem__
для поддержки как строковых, так и перечислимых типов.
Ваша цель - получить параметр метода и преобразовать его в строку, если это перечисление. Таким образом, можно получить и сохранить строковые значения с помощью переменной enum.
Ваш код должен выглядеть следующим образом:
from collections import UserDict
from enum import Enum
class EnumDict(UserDict):
def __setitem__(self, key, value):
string_key = key.value if isinstance(key, Enum) else key
super().__setitem__(string_key, value)
def __getitem__(self, item):
string_item = item.value if isinstance(item, Enum) else item
return super().__getitem__(string_item)
Обратите внимание, что это сработает, только если вы на самом деле наследуете от UserDict
.
Пожалуйста, прочитайте этот отличный пост в блоге " Проблема с наследованием от dict и list в Python ", чтобы понять, почему я использую UserDict
вместо обычного dict
. В противном случае вам также потребуется переопределить методы __init__
, update
и get
.
Обратите внимание, что если вы используете python2 (что делать не следует, поскольку он больше не поддерживается), приведенный выше код не будет работать, поскольку UserDict
используется как средство обратной совместимости для время, в которое вы не можете наследовать напрямую от dict
. Он не обладает тем же набором функций и возможностей, что и в python3.
В любом случае, если вы используете python2 или просто не хотите наследовать от UserDict
, ваш код должен выглядеть так:
from enum import Enum
class EnumDict(dict):
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
def update(self, *args, **kwargs):
try:
for key, value in args[0].items():
self.__setitem__(key, value)
except Exception:
super().update(*args, *kwargs)
def __setitem__(self, key, value):
string_key = key.value if isinstance(key, Enum) else key
super().__setitem__(string_key, value)
def __getitem__(self, item):
string_item = item.value if isinstance(item, Enum) else item
return super().__getitem__(string_item)
def get(self, key, default=None):
string_key = key.value if isinstance(key, Enum) else key
return super().get(string_key, default)
Для суммирования вверх, вся идея здесь заключается в приведении enum к его строковому значению.
При использовании dict
, а не UserDict
, нужно также позаботиться об инициализации, обновлении и регулярных процессах get - убедившись, что вы не будете застрять с перечислениями вместо обычных строк.
Вот пример того, как работает этот словарь:
In [1]: class Test(Enum):
...: A = "abc"
...: B = "xyz"
...: C = "qwerty"
In [2]: my_dict = EnumDict({"ok": "fine", Test.B: "bla-bla"})
In [3]: my_dict
Out[3]: {'ok': 'fine', 'xyz': 'bla-bla'}
In [4]: my_dict[Test.A] = "hello"
In [5]: my_dict["testing"] = "works"
In [6]: my_dict
Out[6]: {'ok': 'fine', 'xyz': 'bla-bla', 'abc': 'hello', 'testing': 'works'}
In [7]: my_dict.update({"isOkay": "yes", Test.B: "wow"})
In [8]: my_dict
Out[8]: {'ok': 'fine', 'xyz': 'wow', 'abc': 'hello', 'testing': 'works', 'isOkay': 'yes'}
In [9]: my_dict.get(Test.C, "does not exist")
Out[9]: 'does not exist'
In [10]: my_dict.get(Test.A)
Out[10]: 'hello'
In [11]: my_dict[Test.A]
Out[11]: 'hello'
In [12]: my_dict["xyz"]
Out[12]: 'wow'