I am writing code, which I want to work both with vanilla Python and as part of a Cythonized module. I have a cdef class that I want to behave normally, but on which I want to override the behaviour of __getattr__
(for undefined attributes). In Python this is simple, however Cython does not behave up to spec:
@cython.cclass
class Test:
field: cython.declare(object, visibility='public')
def __init__(self):
self.field = 24
def __getattr__(self, item):
return 42
The expression Test().field
, in Python, returns 24, as it should, and Test().anything_else
gives 42
. In Cython, Test().field
returns 42
as __getattr__
is treated as if it was a __getattribute__
. I do not want my object to have dynamic fields, I merely want to override the behaviour of the .
operator for when a property is not found, as in vanilla Python.
I know I can define __getattr__
as:
def __getattr__(self, item):
if item == 'field':
return self.field
return 42
But once you get a few properties this becomes tedious.
Is there a better way?
As noticed by @user2357112 in the comment my example contains a typo in the use of cython.declare
, it should use =
not :
:
@cython.cclass
class Test:
field = cython.declare(object, visibility='public')
def __init__(self):
self.field = 24
def __getattr__(self, item):
return 42
This fixes the problem for me.