Issue
I have a Python module which defines class A with subclass B. Class A defines a property with a getter and setter, class B overrides the setter:
import abc
class A:
__metaclass__ = abc.ABCMeta
def __init__(self):
self.__x = 0
@property
def x(self):
return self.__x
@x.setter
def x(self, newX):
print("Setter in class A")
self.__x = newX
class B(A):
@A.x.setter
def x(self, newX):
print("Setter in class B")
A.x.fset(self, newX)
b = B()
b.x = 42
print(b.x)
When I let Cython compile the module and then import it, Python prints the desired output:
Setter in class B
Setter in class A
42
Running it as a pure Python module (without Cython compilation) also gives me the desired output.
For performance reasons, I'd like to turn A into an extension type by changing line 3 to:
cdef class A:
With this, Cython compilation remains possible, but then I get this exception at runtime: File "test.pyx", line 21, in init test @A.x.setter AttributeError: 'getset_descriptor' object has no attribute 'setter'
Is there a different way to override the setter, so that it also works with a cdef class?
Solution
For performance reasons, I'd like to turn A into an extension type [...]
One thing worth emphasising - by using a cdef class
you are trading flexibility for performance so this sort of thing not working is expected.
What I'd do in this case is have the setter in A
call an implementation function, and override the implementation function in B
. If B
is a cdef class
then the implementation function can be cdef
. Otherwise it needs to be cpdef
(or def
):
cdef class A:
...
@x.setter
def x(self, newX):
self.xSettingImpl(newX)
cpdef xSetterImpl(self, newX):
print("Setter in class A")
self.__x = newX
class B:
def xSetterImpl(self, newX):
print("Setter in class B")
A.x.fset(self, newX) # Not sure this is likely to work though...
Also, I don't think this will work in a cdef class
:
__metaclass__ = abc.ABCMeta
Answered By - DavidW
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.