python3单例模式与"与"声明

时间:2016-07-07 06:28:34

标签: python python-3.x contextmanager

我想用singleton模式编写一个类,使用pickle / dict提供一些持久的数据存储:

@singleton
class Pdb:
    def __init__(self):
        self.cache = None
        self.dirty = False
        try:
            with open("data.pck","rb") as fp:
                self.cache = pickle.load(fp)
        except FileNotFoundError:
            pass
        except pickle.PickleError:
            pass

        if self.cache is None:
            self.cache = {}

    def flush(self):
        if self.dirty:
            try:
                with open("data.pck","wb") as fp:
                    pickle.dump(self.cache,fp,protocol=4)
            except pickle.PickleError:
                pass
            else:
                self.dirty = False

    def __del__(self): # PROBLEM HERE
        self.flush()

当我使用python 2时,我可以通过覆盖__del__来实现。但它在python 3中似乎不正确。我该怎么办?

如果我用"用"声明,我需要将实例传递给我调用的每个函数:

def func1(db):
    db.set(...)
    func3(db,x1,x2,...)

with Pdb() as db:
    func1(db)
    func2(db)

这很复杂。是否有一种pythonic方式来实现全球范围"与"声明?

1 个答案:

答案 0 :(得分:1)

  

如果我用"用"声明,我需要将实例传递给我调用的每个函数:

不,你不是。只需使用你的单身人士:

# global
db = Pdb()

# any other context
with db:

所需要的只是表达式生成一个上下文管理器。使用__enter____exit__方法引用单个对象将满足该要求。您甚至可以忽略__enter__返回值,就像我上面所做的那样。全局仍可用于您的所有功能,唯一可以改变的是__enter____exit__将在适当的位置调用。

请注意,即使在Python 2中,您也应该依赖于__del__被调用。在CPython实现中,在循环引用之外,调用__del__时的规则在Python 2和3之间没有变化。