在Singleton/Borg内部调用时未执行QTimer

2024-04-24 01:21:19 发布

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

我在单例中使用QTimer实现了一个计时器。单例使用Borg模式实现。如果我在Singleton函数中用singleshot启动一个QTimer,它不会被执行。在Singleton之外的函数中进行相同的调用效果良好。在

代码如下:

#!/usr/bin/env python
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication


class Borg():
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state


class Timers(Borg):
    def __init__(self):
        Borg.__init__(self)

    def update_not_working(self):
        QTimer().singleShot(2000, Timers().update_not_working)
        print('update not working')


def update_working():
    QTimer().singleShot(2000, update_working)
    print('update working')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    print('start timer')
    Timers().update_not_working()
    update_working()

    sys.exit(app.exec_())

输出为(无错误,无异常):

^{pr2}$

为什么一个电话有效,另一个却不行?我对Borg的实现或者QTimer的使用有什么问题吗?在


Tags: 函数importselfinitdefsysnotupdate
3条回答
class Borg():
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state


class Timers(Borg):
    def __init__(self):
        Borg.__init__(self)

    @classmethod
    def update_not_working(cls):
        QTimer().singleShot(2000, Timers().update_not_working)
        print('update not working')


def update_working():
    QTimer().singleShot(2000, update_working)
    print('update working')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    print('start timer')
    Timers().update_not_working()
    update_working()
    sys.exit(app.exec_())

这实际上只是一个普通的垃圾收集问题。在

如果像这样向示例中添加一些调试代码:

class Timers(Borg):
    def __init__(self):
        Borg.__init__(self)
        print('init:', self)

    def update_not_working(self):
        QTimer().singleShot(1, Timers().update_not_working)
        print('update not working')

    def __del__(self):
        print('deleted:', self)

它将产生如下输出:

^{pr2}$

如您所见,这两个Timers实例在单次计时器发送其timeout()信号之前就被删除了。当它们删除时,它们的实例方法也会被删除,这将自动断开它们与信号的连接。这表明Borg模式并不能产生真正的单例:它只是模仿一个模式的一些行为。在

如果使用real单例类,如下所示:

class Timers2(object):
    _instance = None

    def __new__(cls):
        if Timers2._instance is None:
            Timers2._instance = object.__new__(cls)
        return Timers2._instance

    def update_not_working(self):
        QTimer().singleShot(2000, Timers2().update_not_working)
        print('update not working')

您的示例将如预期的那样工作。这是因为只有一个实例,并且它通过作为类属性缓存而保持活动。在

最后,update_working()成功的原因是它是一个全局定义的函数。与class属性一样,这确保在脚本完成之前不会被垃圾回收。在

update_not_working中的print self和{}中的print Timers()表明事件循环开始之前的Timers对象与中的对象不同:

update not working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>

@classmethod在这里应该有帮助,因为它允许像在single shot语句中那样对实例或类调用方法。在

比较:When should I use @classmethod and when def method(self)?

相关问题 更多 >