在查看Think Complexity中的一些代码时,我注意到他们的Graph
类为自己分配了值。我已经复制了该类中的一些重要行,并编写了一个示例类ObjectChild
,但这种行为失败了。
class Graph(dict):
def __init__(self, vs=[], es=[]):
for v in vs:
self.add_vertex(v)
for e in es:
self.add_edge(e)
def add_edge(self, e):
v, w = e
self[v][w] = e
self[w][v] = e
def add_vertex(self, v):
self[v] = {}
class ObjectChild(object):
def __init__(self, name):
self['name'] = name
我确定不同的内置类型都有自己的使用方法,但我不确定这是否应该尝试构建到我的类中。有可能,怎么样?这是我不应该打扰的东西,而是依赖于简单的构图,例如self.l = [1, 2, 3]
?应该在内置类型之外避免吗?
我问,因为我被告知“你几乎不应该继承内置的python集合”;建议我犹豫是否要限制自己。
为了澄清,我知道ObjectChild
不会“正常工作”,我可以轻松地使“工作”,但我很好奇这些内置的工作原理在类型中,使其界面与object
的孩子不同。
答案 0 :(得分:7)
他们通过继承dict
来实现这种魔力。更好的方法是继承UserDict或更新的collections.MutableMapping
你可以通过做同样的事情来完成类似的结果:
import collections
class ObjectChild(collections.MutableMapping):
def __init__(self, name):
self['name'] = name
您还可以定义两个特殊功能,使您的类字典类似:__getitem__(self, key)
和__setitem__(self, key, value)
。您可以在Dive Into Python - Special Class Methods找到相关示例。
答案 1 :(得分:5)
免责声明:我可能错了。
符号:
self[something]
在Graph类中是合法的,因为它继承了dict。这种表示法来自词典ssyntax,而不是来自类属性声明语法。
虽然与类关联的所有命名空间都是字典,但在类ChildObject中,self不是字典。因此,您无法使用该语法。
Otoh,在你的类Graph中,self是一个词典,因为它是一个图形,所有图形都是字典,因为它们是从dict继承的。
答案 2 :(得分:4)
只需将以下简单函数添加到您的类中即可:
class some_class(object):
def __setitem__(self, key, value):
setattr(self, key, value)
def __getitem__(self, key):
return getattr(self, key)
答案 3 :(得分:3)
使用这样的东西好吗?
def mk_opts_dict(d):
''' mk_options_dict(dict) -> an instance of OptionsDict '''
class OptionsDict(object):
def __init__(self, d):
self.__dict__ = d
def __setitem__(self, key, value):
self.__dict__[key] = value
def __getitem__(self, key):
return self.__dict__[key]
return OptionsDict(d)
答案 4 :(得分:2)
您的ObjectChild不起作用,因为它不是dict的子类。这些都可以起作用:
class ObjectChild(dict):
def __init__(self, name):
self['name'] = name
或
class ObjectChild(object):
def __init__(self, name):
self.name = name
答案 5 :(得分:2)
我意识到这是一篇过时的文章,但是我一直在寻找有关项目分配的一些细节,并偶然发现了这里的答案。 Ted's post并非完全错误。为了避免从dict继承,可以使一个类从MutableMapping继承,然后为__setitem__
和__getitem__
提供方法。
此外,该类将需要支持__delitem__
,__iter__
,__len__
和(可选)其他继承的混合方法(如pop
)的方法。该文档提供了有关详细信息的更多信息。
from collections.abc import MutableMapping
class ItemAssign(MutableMapping):
def __init__(self, a, b):
self.a = a
self.b = b
def __setitem__(self, k, v):
if k == "a":
self.a = v
if k == "b":
self.b = v
def __getitem__(self, k):
if k == "a":
return self.a
if k == "b":
return self.b
def __len__(self):
return 2
def __delitem__(self, k):
self[k] = None
def __iter__(self):
yield self.a
yield self.b
示例用法:
>>> x = ItemAssign("banana","apple")
>>> x["a"] = "orange"
>>> x.a
'orange'
>>> del x["a"]
>>> print(x.a)
None
>>> x.pop("b")
'apple'
>>> print(x.b)
None
希望这有助于阐明如何为在此帖子中绊脚的其他人正确实施项目分配:)
答案 6 :(得分:0)
你不需要继承dict。如果您提供 setitem 和 getitem 方法,您也会获得我认为的理想行为。
class a(object):
def __setitem__(self, k, v):
self._data[k] = v
def __getitem__(self, k):
return self._data[k]
_data = {}
答案 7 :(得分:0)
对于那些想要继承字典的人。 在这种情况下,MyDict中将包含原始字典的浅表副本。
class MyDict(dict):
...
d = {'a': 1}
md = MyDict(d)
print(d['a']) # 1
print(md['a']) # 1
md['a'] = 'new'
print(d['a']) # 1
print(md['a']) # new
当您有一棵嵌套的字典树并且想要将其一部分隐蔽到一个对象时,这可能会导致问题。更改该对象不会影响其父对象
root = {
'obj': {
'a': 1,
'd': {'x': True}
}
}
obj = MyDict(root['obj'])
obj['a'] = 2
print(root) # {'obj': {'a': 1, 'd': {'x': True}}} # 'a' is the same
obj['d']['x'] = False
print(root) # {'obj': {'a': 1, 'd': {'x': True}}} # 'x' chanded