是否可以使用super()的方法,否则会隐式使用?

2024-05-23 22:29:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我想重写dict,这样修改一个键就可以在修改后将dict转储到pickle中。你知道吗

为此,我重写了__setitem__。代码如下:

  • 如果空的“缓存”(转储的pickle)不存在,则初始化它
  • 或加载其内容(如果缓存存在)
  • 修改__setitem__以添加转储

很好用。但是,我需要说明这样一个事实:pickle.load()在构建dict时也使用了__setitem__,并且不应该在那时尝试将其转储到do磁盘(因为它实际上是从磁盘加载的)。我用的方法看起来很可怕。你知道吗

import pickle
import myconfig  # en extension of logging to format logs across my scripts via myconfig.log
import sys

class CachedDict(dict):
    def __init__(self, db="cache.pickle", **kwargs):
        super().__init__()
        self.db = db
        try:
            # load the axisting cache, if any
            with open(self.db, 'rb') as f:
                data = pickle.load(f)
            self.update(data)
        except FileNotFoundError:
            # failed to load the cache, create a new one
            myconfig.log.info("no cache {db} found, initializing".format(db=self.db))
            with open(self.db, 'wb') as f:
                pickle.dump(self, f)
        else:
            myconfig.log.info("loading from {db} cached dict {self}".format(self=self, db=self.db))

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        # dump cache
        myconfig.log.debug("updating dict {self} with {key}, {value}".format(self=self, key=key, value=value))
        # do not write the cache when called from __init__: we are populating the dict
        if sys._getframe(1).f_code.co_name != '__init__':
            try:
                with open(self.db, 'wb') as f:
                    pickle.dump(self, f)
            except Exception as e:
                myconfig.log.error("cannot update cache: {e}".format(e=e))


a = CachedDict("hello.pickle")
a['hello'] = 'world'
a[3] = 5
a['hello'] = 'wazaa'
myconfig.log.debug("final dict: {a}".format(a=a))

这个输出

2016-01-11 12:59:54,134 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5} with 3, 5
2016-01-11 12:59:54,134 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'wazaa'} with hello, wazaa
2016-01-11 12:59:54,136 | INFO | scratch_48 | 20 | __init__ | loading from hello.pickle cached dict {3: 5, 'hello': 'wazaa'}
2016-01-11 12:59:54,136 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'world'} with hello, world
2016-01-11 12:59:54,137 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'world'} with 3, 5
2016-01-11 12:59:54,138 | DEBUG | scratch_48 | 25 | __setitem__ | updating dict {3: 5, 'hello': 'wazaa'} with hello, wazaa
2016-01-11 12:59:54,139 | DEBUG | scratch_48 | 39 | <module> | final dict: {3: 5, 'hello': 'wazaa'}

问题就在这条线上

data = pickle.load(f)

有没有一种方法可以指示Python对这种情况使用super()版本的__setitem__?你知道吗


Tags: debugselflogformatcachehellodbwith
2条回答

在dict更新并关闭文件后,立即将数据写入文件, 如何防止此CachedDict可能被多个线程调用,也可能被用户在两次调用的间隔内修改泡菜。垃圾?你知道吗

你能在CachedDict中包装一个普通的dict,然后在调用时转储并关闭文件吗cachedDict.关闭显式地(或在\u del\u中)?你知道吗

这个怎么样,我觉得委派比继承好

class CachedDict():
    def __store(self):
        try:
            with open(self.db, 'wb') as f:
                pickle.dump(self.__dict, f)
        except Exception as e:
            print  "cannot update cache: {e}".format(e=e)
    def __init__(self, db="cache.pickle", **kwargs):
        self.__dict = {}
        self.db = db
        try:
            # load the axisting cache, if any
            with open(self.db, 'rb') as f:
                data = pickle.load(f)
            self.update(data)
        except:
            self.__store()

    def __setitem__(self, key, value):
        self.__dict[key] = value
        self.__store()
    def __str__(self):
        return self.__dict.__str__()

相关问题 更多 >