Reputation: 358
In the following sample code, a cython class (Q) is imported. Two instances of Q are created (q1 and q2). I'd like to alter a variable inside q1 and have it affect the same variable inside q2.
Thank you very much for your time and any related information on scope or inheritance in Cython!
tc1.pyx:
cimport cython
cdef class Q:
cdef public double q
def __cinit__(self):
self.q = 0
def addone(self):
self.q += 1
property gsd: # get set return
def __get__(self):
return self.q
def __set__(self, value):
pass
def __del__(self):
pass
.py file:
from tc1 import Q
if __name__ == "__main__":
q1 = Q()
q2 = Q()
print 'q1: ', q1.gsd, 'q2: ', q2.gsd # >> 0 and 0
q1.addone()
print 'q1: ', q1.gsd, 'q2: ', q2.gsd # >> 1 and 0 (1 and 1 desired)
Upvotes: 1
Views: 821
Reputation: 3184
Cython classes compile to C, where the class members are just values in a struct; so there's no notion of static variables for cdef classes.
You can simply declare a global pointer that Q references, however:
cimport cython
from libc.stdlib cimport malloc, free
cdef public double* global_q = <double*>malloc(sizeof(double))
global_q[0] = 0
def call_at_end():
free(global_q)
cdef class Q:
cdef double* q
def __cinit__(self):
self.q = global_q
def addone(self):
self.q[0] += 1
property gsd:
def __get__(self):
return self.q[0]
def __set__(self, double value):
self.q[0] = value
Now your main function will work as expected. I added the function call_at_end to free the memory just to show how you would do it, but in this case you would never free the memory for as long as you could make an instance of Q.
Upvotes: 1
Reputation:
I'm not sure how you do it in Cython, but here is an attempt that solves it in regular Python. I'd presume if you change the propery code to use Cython decorators it should work fine.
First you need a class variable, for example _bar
, then we adjust the property getter and setter methods to alter this, instead of an instance variable. The code below should illustrate this and you can verify it works on IdeOne:
class Foo(object):
_bar = 0
@property
def bar(self):
return Foo._bar
@bar.setter
def bar(self, value):
Foo._bar = value
@bar.deleter
def bar(self):
pass
a = Foo()
b = Foo()
print a.bar
print b.bar
a.bar += 1
print a.bar
print b.bar
This outputs the below as desired:
0
0
1
1
Upvotes: 1