一个像字典的Python类
我想写一个自定义的类,让它的行为像 dict
(字典)一样,所以我打算从 dict
继承。
不过,我有个问题:我在 __init__()
方法里需要创建一个私有的 dict
成员吗?我觉得没必要,因为我直接继承 dict
就已经有字典的功能了。
有没有人能告诉我,为什么大多数继承的示例看起来像下面这个?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
而不是更简单的...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
其实,我觉得这个问题的答案可能是为了让用户不能直接访问你的字典(也就是说,他们必须使用你提供的访问方法)。
但是,关于数组访问操作符 []
呢?那该怎么实现呢?到目前为止,我还没看到过一个示例展示如何重写 []
操作符。
所以,如果在自定义类中没有提供 []
访问函数,继承的基类方法会在一个不同的字典上操作吗?
我尝试了下面的代码片段来测试我对 Python 继承的理解:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(self, id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
print md[id]
结果我遇到了以下错误:
KeyError: < built-in function id>
上面的代码有什么问题吗?
我该如何修正 myDict
类,以便我可以写出这样的代码?
md = myDict()
md['id'] = 123
[编辑]
我已经编辑了上面的代码示例,修正了我之前匆忙离开桌子时犯的愚蠢错误。那是个拼写错误(我应该从错误信息中发现它)。
11 个回答
122
像这样
class CustomDictOne(dict):
def __init__(self, *arg, **kw):
super(CustomDictOne, self).__init__(*arg, **kw)
现在你可以使用内置的函数,比如 dict.get()
,就像用 self.get()
一样。
你不需要再包裹一个隐藏的 self._dict
。你的类已经就是一个字典了。
147
class Mapping(dict):
def __setitem__(self, key, item):
self.__dict__[key] = item
def __getitem__(self, key):
return self.__dict__[key]
def __repr__(self):
return repr(self.__dict__)
def __len__(self):
return len(self.__dict__)
def __delitem__(self, key):
del self.__dict__[key]
def clear(self):
return self.__dict__.clear()
def copy(self):
return self.__dict__.copy()
def has_key(self, k):
return k in self.__dict__
def update(self, *args, **kwargs):
return self.__dict__.update(*args, **kwargs)
def keys(self):
return self.__dict__.keys()
def values(self):
return self.__dict__.values()
def items(self):
return self.__dict__.items()
def pop(self, *args):
return self.__dict__.pop(*args)
def __cmp__(self, dict_):
return self.__cmp__(self.__dict__, dict_)
def __contains__(self, item):
return item in self.__dict__
def __iter__(self):
return iter(self.__dict__)
def __unicode__(self):
return unicode(repr(self.__dict__))
o = Mapping()
o.foo = "bar"
o['lumberjack'] = 'foo'
o.update({'a': 'b'}, c=44)
print 'lumberjack' in o
print o
In [187]: run mapping.py
True
{'a': 'b', 'lumberjack': 'foo', 'foo': 'bar', 'c': 44}
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。
48
查看一下关于模拟容器类型的文档。在你的情况下,add
函数的第一个参数应该是self
。