一个类似字典的python类

一个类似字典的python类

问题描述:

我想写一个自定义类,其行为类似于dict--所以我从dict继承。一个类似字典的python类

但我的问题是:我是否需要在我的__init__()方法中创建私人dict成员?我没有看到这一点,因为我已经有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 

[编辑]

我已编辑的代码示例上述摆脱之前我虚线从我的办公桌前我做了愚蠢的错误。这是一个错字(我应该从错误信息中发现它)。

+23

我经常被称为“行为像字典的程序员。 – 2010-10-25 12:44:53

+1

可能重复[Python:如何“完美”重写一个字典](http://*.com/questions/3387691/python-how-to-perfectly-override-a-dict) – 2015-01-06 21:57:04

检查文档emulating container types。在你的情况下,add的第一个参数应该是self

与此块的代码的问题:

class myDict(dict): 
    def __init__(self): 
     self._dict = {} 

    def add(id, val): 
     self._dict[id] = val 


md = myDict() 
md.add('id', 123) 

...是你的“添加”的方法(...你想成为一个类的成员的任何方法)需要有一个明确的“自我”宣布为它的第一个参数,如:

def add(self, 'id', 23): 

要实现运算符重载通过密钥才能访问项目,看在docs的魔术方法__getitem____setitem__

请注意,由于Python使用Duck Typing,实际上可能没有理由从语言的dict类派生自定义的dict类 - 而无需知道更多关于您想要做什么的事情(例如,如果您需要通过这个类的一个实例放入某个代码中,除非isinstance(MyDict(), dict) == True),否则只需实现使您的类充分类字体化并停止在那里的API就可能会更好。

像这样

class CustomDictOne(dict): 
    def __init__(self,*arg,**kw): 
     super(CustomDictOne, self).__init__(*arg, **kw) 

现在你可以使用内置的功能,如dict.get()self.get()。您不需要隐藏self._dict。您的班级已经 a字典。

+0

这个。没有先调用它的构造函数从''dict''继承是没有意义的。 – sykora 2010-10-25 14:19:34

+1

请注意,您的继承'dict'实际上包含2个dict-instance:第1个是继承的容器,第2个是持有类属性的dict - 您可以通过使用[__slots__](https:// docs。 python.org/3/reference/datamodel.html#slots)。 – ankostis 2016-03-04 10:37:19

+1

'__dict__'实际上只在第一次访问时才被创建,所以只要用户不尝试使用它,就没有问题。 '__slots__'虽然不错。 – 2017-01-08 00:41:21

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} 
+13

如果你要继承'dict',那么你应该使用对象本身(使用'super')而不是简单地委托给实例的'__dict__' - 这意味着你要为每个对象创建两个字典实例。 – 2017-01-08 00:39:48

为了完整起见,这里是链接到由@提到的文件比约恩 - 博动获得最新的Python 2.x的(2.7.7截至截稿时):

Emulating Container Types

(对不起,不使用评论功能,我只是不被允许通过计算器这样做。)