问题:一个像dict一样的python类
我想编写一个行为类似的自定义类dict
-因此,我继承自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:<内置函数ID>
上面的代码有什么问题?
如何更正该类,myDict
以便可以编写这样的代码?
md = myDict()
md['id'] = 123
[编辑]
我已经编辑了上面的代码示例,以摆脱在离开办公桌前犯下的愚蠢错误。这是一个错字(我应该从错误消息中发现它)。
回答 0
查看有关模拟容器类型的文档。您的情况下,第一个参数add
应为self
。
回答 1
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}
回答 2
像这样
class CustomDictOne(dict):
def __init__(self,*arg,**kw):
super(CustomDictOne, self).__init__(*arg, **kw)
现在你可以使用内置的功能,如dict.get()
作为self.get()
。
您无需包装隐藏的self._dict
。您的类已经是字典。
回答 3
为了完整起见,这里是@björn-pollex提到的有关最新Python 2.x(截至撰写本文时为2.7.7)的文档的链接:
(很抱歉,您未使用注释功能,但是stackoverflow不允许这样做。)
回答 4
此代码段的问题:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
…是您的’add’方法(…以及您想成为类成员的任何方法)需要声明一个明确的’self’作为其第一个参数,例如:
def add(self, 'id', 23):
要实现操作符重载以按键访问项目,请在文档中查找magic方法__getitem__
和__setitem__
。
请注意,由于Python使用Duck Typing,因此实际上可能没有理由从语言的dict类派生自定义dict类-无需更多了解您要执行的操作(例如,如果需要传递此方法的实例)类插入某个可能会中断的代码(除非isinstance(MyDict(), dict) == True
),您最好实现一个使类足够像字典的API,然后停在那里。
回答 5
这是一个替代解决方案:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
a = AttrDict()
a.a = 1
a.b = 2
回答 6
我真的在任何地方都看不到正确的答案
class MyClass(dict):
def __init__(self, a_property):
self[a_property] = a_property
您真正要做的就是定义自己的__init__
-确实就是它的全部。
另一个例子(稍微复杂一点):
class MyClass(dict):
def __init__(self, planet):
self[planet] = planet
info = self.do_something_that_returns_a_dict()
if info:
for k, v in info.items():
self[k] = v
def do_something_that_returns_a_dict(self):
return {"mercury": "venus", "mars": "jupiter"}
当您想嵌入某种逻辑时,这最后一个例子很方便。
总之……简而言之class GiveYourClassAName(dict)
,足以使您的课堂像字典一样行事。您执行的任何dict操作都self
将像常规dict。
回答 7
这是我最好的解决方案。我使用了很多次。
class DictLikeClass:
...
def __getitem__(self, key):
return getattr(self, key)
def __setitem__(self, key, value):
setattr(self, key, value)
...
您可以这样使用:
>>> d = DictLikeClass()
>>> d["key"] = "value"
>>> print(d["key"])
回答 8
永远不要继承自Python内置字典!例如update
方法woldn’t use __setitem__
,他们做了很多优化工作。使用UserDict。
from collections import UserDict
class MyDict(UserDict):
def __delitem__(self, key):
pass
def __setitem__(self, key, value):
pass