为什么dict(dict)获得相同的字典?

时间:2017-03-22 02:57:19

标签: python

这可能听起来很愚蠢。当我在python中覆盖dict时:

class idict(dict):
    def __init__ (self, *args, **kwargs):
        self._store = dict(*args, **kwargs)

然后我用

a = {1:2, 2:3}
b=idict(a)
print b._store == a

给出True

我不知道为什么dict(dict)获得相同的词典。在python中的dict有任何方法处理这个吗?我不确定我是否以正确的方式做到了。

这个问题的另一个问题是:

如果我知道我将获得父类实例(如dict),我想在此实例中添加/更改方法。我通常从父类创建子类并获取子类实例。这似乎是内存效率低下的,因为父实例已经存在。

我搜索后的一种方法是直接在父类中添加/更改方法(例如parent_class.method = new_method),然后获取父类的实例。我不确定这在OOP方面是否正确。

1 个答案:

答案 0 :(得分:5)

它没有得到相同的dict。它会对原始dict进行浅层复制,而==则按值进行比较,而不是按身份进行比较,因为它具有所有相同的键和值,它相等,即使它不是相同的 dict

如果您测试了print b._store is a,那么您将获得False,因为is会测试对象标识。

至于你的另一个问题,我并不是100%确定你在那里做什么,但我认为你反对这样一个事实,即你并没有从继承中获益来自dict,因为您仍然拥有存储所有值的属性。这只是因为你在这里没有正确地进行继承。您必须委托父类的方法,而不是制作自己的_store属性,并且您将重用父级的存储。例如,这里正确的__init__将是:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs) # On Py2 super(idict, self) needed instead of super()

现在你根本没有_store,你通过将工作传递给链来初始化父类存储。

旁注:从技术上讲,正确的__init__将是:

def __init__(*args, **kwargs):
    if not args:
        raise TypeError("descriptor '__init__' of 'Counter' object "
                        "needs an argument")
    self = args[0]
    if len(args) > 2:
        raise TypeError('expected at most 1 arguments, got %d' % len(args))

    super(idict, self).__init__(*args[1:], **kwargs)

这是一种特殊情况,仅适用于接受任意关键字的方法,您需要检测并正确响应调用者可能在不引发异常的情况下传递self=someval的可能性(例如,在{ {1}},dict是合法的)。像dict(self="abc")这样的Python dict子类使用这种技术。