Singletons do not work in Cython… here is a solution to the problem.
Singletons do not work in Cython
This is how I define singletons.
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
Then I define my class as:
class MyClass(object):
__metaclass__ = Singleton
def __init__(self):
pass
a = MyClass()
b = MyClass()
“a is b” returns True
But,
cdef class MyCythonClass(object):
__metaclass__ = Singleton
def __cinit__(self):
pass
c = MyCythonClass()
d = MyCythonClass()
“c is d” returns False
I
think this is c code (cinit) running before init, so I tried putting cinit back into init and it doesn’t work either.
If I remove “cdef” before “class”, the problem is solved
I
wonder why, maybe I’m missing something important here. Thank you very much for your help.
Win 10/Python 2.7
Solution
Cython doesn’t seem to support metaclasses out of the box. However this module may provide a workaround.
Implementing a singleton as follows may be another (safer) option:
cdef class Singleton:
_instances = {}
@classmethod
def instance(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = cls(*args, **kwargs)
return cls._instances[cls]
cdef class MyCythonClass(Singleton):
pass
c = MyCythonClass.instance()
d = MyCythonClass.instance()
c is d # True