我在单例中使用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的使用有什么问题吗?在
这实际上只是一个普通的垃圾收集问题。在
如果像这样向示例中添加一些调试代码:
它将产生如下输出:
^{pr2}$如您所见,这两个
Timers
实例在单次计时器发送其timeout()
信号之前就被删除了。当它们删除时,它们的实例方法也会被删除,这将自动断开它们与信号的连接。这表明Borg
模式并不能产生真正的单例:它只是模仿一个模式的一些行为。在如果使用real单例类,如下所示:
您的示例将如预期的那样工作。这是因为只有一个实例,并且它通过作为类属性缓存而保持活动。在
最后,
update_working()
成功的原因是它是一个全局定义的函数。与class属性一样,这确保在脚本完成之前不会被垃圾回收。在update_not_working
中的print self
和{print Timers()
表明事件循环开始之前的Timers
对象与中的对象不同:@classmethod在这里应该有帮助,因为它允许像在single shot语句中那样对实例或类调用方法。在
比较:When should I use @classmethod and when def method(self)?
相关问题 更多 >
编程相关推荐