singleton in python, with qobject
Solved
Language Bindings
-
i need a singleton class, so here's what i got:
__instances = {} class _Singleton(type): def __new__(meta, name, bases, members): for class_ in bases: if class_ is not Singleton and issubclass(class_, Singleton): raise TypeError(("Invalid base type (as subclass of Singleton):", class_)) return type.__new__(meta, name, bases, members) def __call__(class_, *args, **kwargs): if class_ is Singleton: raise TypeError("The base Singleton type cannot be instantiated") if class_ not in __instances: __instances[class_] = super(_Singleton, class_).__call__(*args, **kwargs) return __instances[class_] Singleton = type('_', (), {}) # dummy type to allow base type creation Singleton = _Singleton('Singleton', (object, ), {})
my controller object is a subclass of
QObject
, and i get an error:class Controller(QObject, '''metaclass='''Singleton): TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
-
The following is my implementation (and a usage example) of a singleton I use regularly:
try: from PyQt5.QtCore import pyqtWrapperType except ImportError: from sip import wrappertype as pyqtWrapperType class Singleton(pyqtWrapperType, type): def __init__(cls, name, bases, dict): super().__init__(name, bases, dict) cls.instance=None def __call__(cls,*args,**kw): if cls.instance is None: cls.instance=super().__call__(*args, **kw) return cls.instance if __name__=="__main__": from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty class MyObject(QObject, metaclass=Singleton): def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) self._x=0 def x(self): return self._x @pyqtSlot(int) def setX(self, x): self._x=x x=pyqtProperty(int, x, setX) print(MyObject().x) MyObject().x=1 print(MyObject().x)
I've actually shared this example/technique so many times now that I just quickly created a git repo (https://github.com/jazzycamel/PyQt5Singleton) and a PyPi package (https://pypi.python.org/pypi/PyQt5Singleton) so you can just install it via pip:
$ pip install PyQt5Singleton
and use it (as above):
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty from PyQt5Singleton import Singleton class MyObject(QObject, metaclass=Singleton): def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) self._x=0 def x(self): return self._x @pyqtSlot(int) def setX(self, x): self._x=x x=pyqtProperty(int, x, setX) if __name__=="__main__": print(MyObject().x) MyObject().x=1 print(MyObject().x)
Hope this helps :)