如何“完美”覆盖一个dict? [英] How to "perfectly" override a dict?
问题描述
尽可能使我们做出完美的的子类。最终目标是拥有一个简单的 dict ,其中的键是小写的。
How can I make as "perfect" a subclass of dict as possible? The end goal is to have a simple dict in which the keys are lowercase.
看起来应该是一些很小的原语集可以重写这项工作,但是我所有的研究和尝试都使得它似乎并非如此:
It would seem that should be some tiny set of primitives I can override to make this work, but all my research and attempts have made it seem like this isn't the case:
-
如果我覆盖
__ getitem __
/__ setitem __
,然后获取
/设置
不工作。
我如何让他们工作?当然,我不需要单独实现它们。
If I override
__getitem__
/__setitem__
, thenget
/set
don't work. How do I make them work? Surely I don't need to implement them individually?
我防止酸洗工作,我需要实现 __ setstate __
etc?
Am I preventing pickling from working, and do I need to implement __setstate__
etc?
Do I need repr
, update
and __init__
?
我应该只是使用mutablemapping (似乎不应该使用 UserDict
或 DictMixin
)?如果是这样,怎么办?文件并不完全启发。
Should I just use mutablemapping (it seems one shouldn't use UserDict
or DictMixin
)? If so, how? The docs aren't exactly enlightening.
这是我第一次去, get ()
至少不起作用,毫无疑问有很多微妙的问题:
Here is my first go at it, get()
doesn't work at least, and no doubt there are many minor subtle problems:
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
# http://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()
推荐答案
您可以使用 ABC s
(抽象基类)从集合模块。它甚至告诉你
如果你错过了一个方法,所以下面是关闭ABC的最小版本。
You can write an object that behaves like a dict quite easily with ABCs (Abstract Base Classes) from the collections module. It even tells you if you missed a method, so below is the minimal version that shuts the ABC up.
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获得一些免费方法:
You get a few free methods from the 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的界面。这正是ABCs所用的。
I wouldn't subclass dict
(or other builtins) directly. It often makes no sense, because what you actually want to do is implement the interface of a dict. And that is exactly what ABCs are for.
这篇关于如何“完美”覆盖一个dict?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!