python3 带有 "with" 语句的单例模式

python3 singleton pattern with "with" statement

我想用单例模式写一个 class 来提供一些使用 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.我该怎么做?

如果我通过 "with" 语句执行此操作,我将需要将实例传递给我调用的每个函数:

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

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

这很复杂。是否有 pythonic 方法来执行全局范围 "with" 语句?

If I do it by "with" statement, I will need to pass the instance to each function that I call:

不,你不知道。只需使用您的单例:

# global
db = Pdb()

# any other context
with db:

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

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