sky*_*gle 97 python dictionary
我想写一个行为类似的自定义类dict- 所以,我继承自dict.
但我的问题是:我是否需要dict在我的__init__()方法中创建一个私有成员?我没有看到这一点,因为我已经有了dict行为,如果我只是继承dict.
任何人都可以指出为什么大多数继承片段看起来像下面的那样?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Run Code Online (Sandbox Code Playgroud)
而不是更简单......
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
Run Code Online (Sandbox Code Playgroud)
实际上,我认为我怀疑这个问题的答案是用户不能直接访问你的字典(即他们必须使用你提供的访问方法).
但是,阵列访问运算符[]呢?如何实现这一点?到目前为止,我还没有看到一个显示如何覆盖[]运算符的示例.
因此,如果[]自定义类中未提供访问函数,则继承的基本方法将在不同的字典上运行?
我尝试了以下代码片段来测试我对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]
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
KeyError:<内置函数id>
上面的代码有什么问题?
如何更正类,myDict以便我可以编写这样的代码?
md = myDict()
md['id'] = 123
Run Code Online (Sandbox Code Playgroud)
[编辑]
我已经编辑了上面的代码示例,以摆脱我在离开桌子之前犯下的愚蠢错误.这是一个错字(我应该从错误信息中发现它).
Ric*_*son 93
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}
Run Code Online (Sandbox Code Playgroud)
S.L*_*ott 74
像这样
class CustomDictOne(dict):
def __init__(self,*arg,**kw):
super(CustomDictOne, self).__init__(*arg, **kw)
Run Code Online (Sandbox Code Playgroud)
现在您可以使用内置函数,如dict.get()as self.get().
你不需要包装一个隐藏的self._dict.你的班级已经是一个词典.
mad*_*gan 13
这是我最好的解决方案。我用过这个很多次。
class DictLikeClass:
...
def __getitem__(self, key):
return getattr(self, key)
def __setitem__(self, key, value):
setattr(self, key, value)
...
Run Code Online (Sandbox Code Playgroud)
你可以这样使用:
>>> d = DictLikeClass()
>>> d["key"] = "value"
>>> print(d["key"])
Run Code Online (Sandbox Code Playgroud)
Aar*_*all 10
一个Python类,其行为类似于
dict
谁能指出为什么大多数继承片段看起来像下面的那样?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
Run Code Online (Sandbox Code Playgroud)
大概有一个很好的理由从 dict 继承(也许你已经在传递一个字典并且你想要一种更具体的字典)并且你有一个很好的理由实例化另一个字典来委托给(因为这将在每个实例实例化两个字典) )但这听起来不正确吗?
我自己从未遇到过这个用例。我确实喜欢在使用可输入的字典的情况下输入字典的想法。但在这种情况下,我更喜欢类型化类属性的想法 - 字典的重点是你可以给它任何可哈希类型的键和任何类型的值。
那么为什么我们会看到这样的片段呢?我个人认为这是一个很容易犯的错误,而且没有得到纠正,因此随着时间的推移会一直存在。
我宁愿在这些片段中看到这样的内容,以通过继承来演示代码重用:
class AlternativeOne(dict):
__slots__ = ()
def __init__(self):
super().__init__()
# other init code here
# new methods implemented here
Run Code Online (Sandbox Code Playgroud)
或者,为了演示重新实现听写的行为,可以这样:
from collections.abc import MutableMapping
class AlternativeTwo(MutableMapping):
__slots__ = '_mydict'
def __init__(self):
self._mydict = {}
# other init code here
# dict methods reimplemented and new methods implemented here
Run Code Online (Sandbox Code Playgroud)
为什么要添加插槽?内置dict实例没有任意属性:
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
Run Code Online (Sandbox Code Playgroud)
如果我们按照大多数人在这个答案中所做的方式创建一个子类,我们会发现我们没有得到相同的行为,因为我们将有一个__dict__属性,导致我们的字典可能占用两倍的空间:
class AlternativeOne(dict):
__slots__ = ()
def __init__(self):
super().__init__()
# other init code here
# new methods implemented here
Run Code Online (Sandbox Code Playgroud)
由于上面没有创建错误,因此上面的类实际上并没有“像dict”那样起作用。
我们可以通过给它空槽来让它像字典一样:
from collections.abc import MutableMapping
class AlternativeTwo(MutableMapping):
__slots__ = '_mydict'
def __init__(self):
self._mydict = {}
# other init code here
# dict methods reimplemented and new methods implemented here
Run Code Online (Sandbox Code Playgroud)
所以现在尝试使用任意属性将会失败:
>>> d = dict()
>>> d.foo = 'bar'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'foo'
Run Code Online (Sandbox Code Playgroud)
这个 Python 类的行为更像是一个dict.
有关如何以及为何使用插槽的更多信息,请参阅此问答:__slots__ 的用法?
这是一个替代解决方案:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
a = AttrDict()
a.a = 1
a.b = 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
112108 次 |
| 最近记录: |