I am trying to expand an existing python source using cython .pxd , as Stefan Bechnel shows in slides 32 through 35 of "Using the Cython Compiler to Write Fast Python Code" .
As part of the exercise, I continue to hit the wall with the __eq__() method in my metaclass. I wish I could choose a simpler case to run Cython, but my production code is not so simple. I prepared a “minimal, complete example” to illustrate the problem ... see the code at the bottom of the question.
Story...
- If I use
cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op): cython complains that Special methods must be declared with 'def', not 'cdef' - If I use
def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op): cython complains that function definition in pxd file must be declared 'cdef inline'
So cython gives me a confusing guide ...
Questions
- I know that pure-python
.pxd have limitations; defines __richcmp__() in my .pxd valid way to use .pxd to extend pure python? - If this is a valid way to use
.pxd , how can I fix this to compile correctly? - If this is not true, can
.pxd enhance my pure python meta-analysis without rewriting the entire metaclass in the .pyx file? (example: class Card in this project )
This is my .pxd ...
### File: car_abc.pxd # cython: infer_types=True cimport cython cdef class Japan_Car_ABC: cpdef public char* model cpdef public char* color def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op): """Ref: http://docs.cython.org/src/userguide/special_methods.html#rich-comparisons""" if op==2: # op==2 is __eq__() in pure python if self.model==other.model: return True return False else: err_msg = "op {0} isn't implemented yet".format(op) raise NotImplementedError(err_msg)
Informational
car_abc.py:
### File: car_abc.py from abc import ABCMeta class Japan_Car_ABC(object): __metaclass__ = ABCMeta def __init__(self, model="", color=""): self.model = model self.color = color def __eq__(self, other): if self.model==other.model: return True return False def __hash__(self): return hash(self.model)
car.py:
from car_abc import Japan_Car_ABC class Lexus(Japan_Car_ABC): def __init__(self, *args, **kwargs): bling = kwargs.pop("bling", True) # bling keyword (default: True) super(Lexus, self).__init__(*args, **kwargs) self.bling = bling class Toyota(Japan_Car_ABC): def __init__(self, *args, **kwargs): super(Toyota, self).__init__(*args, **kwargs) if __name__=="__main__": gloria_car = Lexus(model="ES350", color="White") jeff_car = Toyota(model="Camry", color="Silver") print("gloria_car.model: {0}".format(gloria_car.model)) print("jeff_car.model: {0}".format(jeff_car.model)) print("gloria_car==jeff_car: {0}".format(gloria_car==jeff_car))
setup.py:
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext ext_modules = [Extension("car_abc", ["car_abc.py"]),
python metaclass cython
Mike pennington
source share