Как я могу сделать максимально "идеальный" подкласс dict? Конечная цель должна иметь простой dict, в котором ключи являются нижним регистром.
Казалось бы, что должен быть некоторый крошечный набор примитивов, которые я могу переопределить для создания этой работы, но согласно всему моему исследованию и попыткам кажется, что это не имеет место:
Если я переопределяю __getitem__
/__setitem__
, затем get
/set
не работать. Как я могу заставить их работать? Конечно, я не должен реализовывать их индивидуально?
Я препятствую тому, чтобы соление работало, и я должен реализовать __setstate__
и т.д.?
Сделайте мне нужно repr
, update
и __init__
?
Если я просто использую mutablemapping (кажется, что не нужно использовать UserDict
или DictMixin
)? Если так, как? Документы не точно поучительны.
Вот мое первое движение в нем, get()
не работает и несомненно существует много других незначительных проблем:
class arbitrary_dict(dict):
"""A dictionary that applies an arbitrary key-altering function
before accessing the keys."""
def __keytransform__(self, key):
return key
# Overridden methods. List from
# https://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
# Note: I'm using dict directly, since super(dict, self) doesn't work.
# I'm not sure why, perhaps dict is not a new-style class.
def __getitem__(self, key):
return dict.__getitem__(self, self.__keytransform__(key))
def __setitem__(self, key, value):
return dict.__setitem__(self, self.__keytransform__(key), value)
def __delitem__(self, key):
return dict.__delitem__(self, self.__keytransform__(key))
def __contains__(self, key):
return dict.__contains__(self, self.__keytransform__(key))
class lcdict(arbitrary_dict):
def __keytransform__(self, key):
return str(key).lower()
Вы можете легко написать объект, который ведет себя как dict, с помощью ABC s (Абстрактные базовые классы) из модуля collections . Это даже говорит вам если вы пропустили метод, то ниже представлена минимальная версия, которая закрывает ABC.
import collections
class TransformedDict(collections.MutableMapping):
"""A dictionary that applies an arbitrary key-altering
function before accessing the keys"""
def __init__(self, *args, **kwargs):
self.store = dict()
self.update(dict(*args, **kwargs)) # use the free update to set keys
def __getitem__(self, key):
return self.store[self.__keytransform__(key)]
def __setitem__(self, key, value):
self.store[self.__keytransform__(key)] = value
def __delitem__(self, key):
del self.store[self.__keytransform__(key)]
def __iter__(self):
return iter(self.store)
def __len__(self):
return len(self.store)
def __keytransform__(self, key):
return key
Вы получаете несколько бесплатных методов из ABC:
class MyTransformedDict(TransformedDict):
def __keytransform__(self, key):
return key.lower()
s = MyTransformedDict([('Test', 'test')])
assert s.get('TEST') is s['test'] # free get
assert 'TeSt' in s # free __contains__
# free setdefault, __eq__, and so on
import pickle
assert pickle.loads(pickle.dumps(s)) == s
# works too since we just use a normal dict
Я бы не стал подклассом dict
(или других встроенных функций) напрямую. Часто это не имеет смысла, потому что на самом деле вы хотите реализовать интерфейс dict . И это именно то, для чего нужны азбуки.