【问题标题】:Lifetime of static class members/class references? [duplicate]静态类成员/类引用的生命周期? [复制]
【发布时间】:2014-11-24 23:36:20
【问题描述】:

我是asked to show how 为特殊记录器的旧栗子做一个类似单例的解决方案。费尽心思指出不做这类事情的原因,但我还是尝试了。

这样做时,我有一个静态类成员意外消失。

有了这个类声明:

epiLogger.py:

import logging

class epiLogger():
    _initialised = {}
    _finalised = {}

    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.name = name
        if not epiLogger._initialised.get(name):
            self.logger.addHandler(logging.StreamHandler())
            self.logger.setLevel(logging.INFO)
            self.logger.info('** My Prologue **')
            epiLogger._initialised[self.name] = True

    def info(self, the_info):
        self.logger.info(the_info)
        print epiLogger._finalised.get(self.name)

    def __del__(self):
        print "destructing", self.name
        if not epiLogger._finalised.get(self.name):
            print "first destruction"
            self.logger.info('** My Epilogue **')
            epiLogger._finalised[self.name] = True

还有这些测试文件:

bar.py:

from epiLogger import *

a = epiLogger("bar")

a.info("foo!")
a.info("bar!")
a.info("party!")

test.py:

import bar

我明白了

~ mgregory$ python test.py
** My Prologue **
foo!
None
bar!
None
party!
None
destructing bar
Exception AttributeError: "'NoneType' object has no attribute '_finalised'" in <bound method epiLogger.__del__ of <epiLogger.epiLogger instance at 0x1004a48c0>> ignored
~ mgregory$  

但如果我只运行 bar.py 文件:

~ mgregory$ python bar.py
** My Prologue **
foo!
None
bar!
None
party!
None
destructing bar
first destruction
** My Epilogue **
~ mgregory$ 

似乎一级间接导致对类本身的引用(访问类变量)变为“无”。

我尝试了一个更简单的测试用例,并没有以这种方式失败(!)

frob.py:

class frob():    
    _nasty_global_thingy = True

    def __init__(self):
        print "initialising a foo", frob._nasty_global_thingy

    def __del__(self):
        print "destroying a foo", frob._nasty_global_thingy

bar.py:

from frob import *

a = frob()
print a

这不会在导入 bar.py 时以同样的方式失败。

我知道这是不尝试这种事情的众多原因之一,但我还是想了解发生了什么。

【问题讨论】:

    标签: python destructor static-members


    【解决方案1】:

    模块全局变量在 Python 退出时被清理,并且在运行 __del__ 挂钩时您的类引用已经消失

    不要指望全局变量仍然存在。而是使用type(self) 来获取类引用:

    def __del__(self):
        print "destructing", self.name
        cls = type(self)
        if not cls._finalised.get(self.name):
            print "first destruction"
            self.logger.info('** My Epilogue **')
            cls._finalised[self.name] = True
    

    这在object.__del__ hook documentation 的大警告 部分中有记录:

    此外,当__del__() 被调用以响应模块被删除时(例如,当程序执行完成时),__del__() 方法引用的其他全局变量可能已经被删除或正在被删除拆除(例如进口机器关闭)。出于这个原因,__del__() 方法应该做到保持外部不变量所需的绝对最小值。

    考虑到模块全局变量是在字典中维护的,因此它们被清除的顺序取决于字典在清除时当前的实现和 Python 版本相关的顺序。

    【讨论】:

    • @GreenAsJade:取决于您的确切 Python 版本,这可能只是掷骰子,因为哈希随机化可能改变了清理全局变量的顺序。
    • 嘿-您添加的文档帮助很大,谢谢!这让我意识到,如果没有别的,我需要考虑“一个 module 被删除意味着什么!?” (我以前只考虑过对象删除!)
    • (原始问题的蹩脚标题 - 我从来没有发现过,在寻找这个答案的时候!:))
    • @GreenAsJade:啊,你有一个老式的 Python 2 类。使用self.__class__ 而不是type(self)。或者使类继承自object
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    相关资源
    最近更新 更多