覆盖Python dict子类中的__setitem__不适用于设置内部项的值

时间:2014-02-16 10:23:15

标签: python dictionary subclass

我正在尝试创建一个用Python处理我的自定义文件类型的类。我希望它的行为与字典完全相同,所以我扩展了内置的dict类,添加了open(实际为__init__)并保存了函数。结构如下:

{
  'A': [
    [1, 'Doe', 'John', '49396928593', '0', '23', '20'],
    [2, 'Smith', 'Mark', '05926836832', '0', '6', '14'],
  ],
  'B': [
    # and so on
  ]
}

所以它基本上是列表列表的字典。

现在我想要一个类变量changed,当对象中的任何内容发生变化时,该变量将被自动设置为True。显然,只有直接在字典中的项目发生更改时,才会触发我的类的__setitem__。有没有办法捕捉我的字典子项的任何变化?

这是我的代码:

import zlib
import json

class MRK(dict):

    def __init__(self, path):
        self.path = path
        self.changed = False

        fp = open(path, "r")
        compressed = fp.read()
        fp.close()      
        json_data = zlib.decompress(compressed)
        data = json.loads(json_data)
        super(MRK, self).__init__(data)

    def __setitem__(self, key, value):
        print "!"
        self.changed = True
        super(MRK, self).__setitem__(key, value)

    def save(self):
        json_data = json.dumps(self)

        compressed = zlib.compress(json_data)
        fp = open(self.path, "w")
        fp.write(compressed)
        fp.close()


f = MRK('dane.mrk')

for c in f:
    print c

    for std in f[c]:
        if std[1]=='Smith':
            std[1] = 'Brown'
        print std

print f.changed # outputs False

f.save()

1 个答案:

答案 0 :(得分:0)

不,没有;您必须为这些对象使用自定义列表对象,并将“已更改”标志传播到父词典或使用中心对象来跟踪更改。

从字典中检索对象后,字典本身就不再与它有关了;例如,您可以将该对象存储在单独的引用中并传递它,而不涉及原始字典。

另一个选择是始终要求对象再次显式设置:

lstobj = yourdict['A']
lstobj[1][1] = 'Sue'
# explicit set to notify `yourdict`
yourdict['A'] = lstobj