python del语句的魔术方法?

时间:2014-02-05 21:14:30

标签: python magic-methods

快速提问,当你说del object时,python调用的神奇方法是什么?我知道它不是__del__而且它不是__delete__,所以如果有的话会被调用?如果没有调用任何内容,那么如何自定义删除对象时发生的事件?


看看下面的例子:

class SingletonError(Exception):
    pass

class Singleton(type):

    def __new__(metacls, name, parents, kwargs):
        cls = super(Singleton, metacls).__new__(metacls, name, parents, kwargs)
        cls._instance = None
        return cls

    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            inst = cls.__new__(cls, *args, **kwargs)
            inst.__init__(*args, **kwargs)
            cls._instance = inst
            return cls._instance
        else:
            raise SingletonError("Cannot initialize multiple singletons.")

class Logger(object, metaclass = Singleton):

    def __new__(cls, *logging_args, **logging_kwargs):
        self = super(Logger, cls).__new__(cls)
        logging_args_dict = {'log%i' % pos : i for pos, i in enumerate(logging_args, 1)}
        kwargs = dict(logging_args_dict, **logging_kwargs)
        self.__dict__ = kwargs
        return self

log = Logger()

当我删除日志时,我希望它再次将Logger._instance设置为None,这样您就可以重新初始化单例。我怎么能这样做?

1 个答案:

答案 0 :(得分:2)

您可以使用weak reference代替;因为所有对Logger()实例的引用都被清除了,所以弱引用不会阻止对象被收获。

import gc
import weakref

def __call__(cls, *args, **kwargs):
    gc.collect()  # optional, clear existing weak references
    inst = cls._instance and cls._instance()  # de-reference the weakref
    if inst is None:
        inst = cls.__new__(cls, *args, **kwargs)
        inst.__init__(*args, **kwargs)
        cls._instance = weakref.ref(inst)
        return inst
    else:
        del inst  # clear local early
        raise SingletonError("Cannot initialize multiple singletons.")

cls._instance现在是一个弱引用对象;你调用它来检索引用的对象,如果它返回None,对象就会消失,你需要创建一个新对象。

考虑到删除不一定是即时的;一旦删除了最后一个常规引用​​,垃圾收集就需要运行以收集对象。

__call__作为{{1}}中的第一行,确保在测试之前清除任何弱反应。