Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一个类似于dict的python类_Python_Dictionary - Fatal编程技术网

一个类似于dict的python类

一个类似于dict的python类,python,dictionary,Python,Dictionary,我想编写一个行为类似于dict的自定义类-因此,我继承了dict 不过,我的问题是:我是否需要在我的\uuu init\uuu()方法中创建一个私有dict成员?。我不明白这有什么意义,因为如果我只是从dict继承,我已经有了dict行为 有人能指出为什么大多数继承片段看起来像下面的那个吗 class CustomDictOne(dict): def __init__(self): self._mydict = {} # other methods follow 而

我想编写一个行为类似于
dict
的自定义类-因此,我继承了
dict

不过,我的问题是:我是否需要在我的
\uuu init\uuu()
方法中创建一个私有
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:<内置函数id>

上面的代码有什么问题

如何更正类
myDict
,以便编写这样的代码

md = myDict()
md['id'] = 123
[编辑]


我编辑了上面的代码示例,以消除我在冲出办公桌之前犯的愚蠢错误。这是一个打字错误(我应该从错误消息中发现的)。

查看上的文档。在您的情况下,
add
的第一个参数应该是
self

这段代码的问题:

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):
要实现通过键访问项目的运算符重载,请在中查找神奇方法
\uuuuu getitem\uuuuuuu
\uuuuuuu setitem\uuuuu

请注意,由于Python使用Duck类型,因此实际上可能没有理由从该语言的dict类派生自定义dict类,而不知道您正在尝试做什么(例如,如果您需要将该类的实例传递到某个代码中,除非
isinstance(MyDict(),dict)=True
),否则该类将在某个地方中断,您最好只是实现一个API,使您的类足够像dict,然后停在那里。

像这样

class CustomDictOne(dict):
   def __init__(self,*arg,**kw):
      super(CustomDictOne, self).__init__(*arg, **kw)
现在您可以使用内置函数,如
dict.get()
作为
self.get()


您不需要包装隐藏的
自我。\u dict
。您的类已经是dict了。

永远不要继承Python内置dict!例如,
update
方法不使用
\uuuuu setitem\uuuuu
,它们为优化做了很多工作。使用UserDict

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}
from collections import UserDict

class MyDict(UserDict):
    def __delitem__(self, key):
        pass
    def __setitem__(self, key, value):
        pass

以下是另一种解决方案:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__dict__ = self

a = AttrDict()
a.a = 1
a.b = 2

我真的找不到正确的答案

类MyClass(dict):
def uu init uu(self,a_属性):
self[a_属性]=a_属性
你真正需要做的就是定义你自己的
\uuuuu init\uuuuu
——这就是它的全部内容

另一个例子(稍微复杂一些):

类MyClass(dict):
定义初始(自我,行星):
自我[行星]=行星
info=self.do\u某事\u返回\u dict()
如果信息:
对于info.items()中的k、v:
自我[k]=v
def do_something_返回命令(self):
返回{“水星”:“金星”、“火星”:“木星”}
当您想要嵌入某种逻辑时,最后一个示例非常方便


无论如何。。。简而言之,
类给你的类命名(dict)
足以让你的类像一个dict。你在
self
上做的任何dict操作都会像一个普通的dict一样。

这是我最好的解决方案。我用过很多次

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"])
一个类似于dict的python类

通过请求-向dict子类添加插槽。 为什么要添加插槽?内置
dict
实例没有任意属性:

>d=dict()
>>>d.foo='bar'
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“dict”对象没有属性“foo”
如果我们按照大多数人在回答这个问题时的方式创建一个子类,我们会发现我们没有得到相同的行为,因为我们将有一个
\uuuuuuu dict\uuuuuu
属性,导致我们的dict可能占用两倍的空间:

my_dict(dict):
“我的dict子类”
md=我的字典()
md.foo='bar'
因为上面没有创建错误,所以上面的类实际上并不起作用,“比如
dict

我们可以通过给它空插槽使它像dict一样工作:

class my_dict(dict):
__插槽\uuux=()
md=我的字典()
因此,现在尝试使用任意属性将失败:

md.foo='bar' 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 AttributeError:“my_dict”对象没有属性“foo” 这个Python类的行为更像是一个
dict


有关如何使用插槽以及为什么使用插槽的更多信息,请参阅此问答:

Python标准库就是为此而设计的。

这一点。从
dict
继承而不首先调用其构造函数是没有意义的。请注意,继承的
dict
实际上包含2个dict实例:第一个是继承的容器,第二个是保存类属性的dict-您可以通过使用来避免这种情况。
\uuu dict\uuu
实际上只在首次访问时创建,所以只要用户不尝试使用它,就可以了<代码>\uuuuu插槽\uuuuu会很好。在逗号后使用空格表示野蛮人!;-)@andrewtavis我已经发布了一个演示插槽的答案。如果您要子类
dict
,那么您应该使用对象本身(使用
sup