Cython Metaclass .pxd: How should I implement `
I am trying to augment an existing python source with a cython .pxd
, as Stefan Behnel illustrates in slides 32 to 35 of "Using the Cython Compiler to write fast Python code".
As part of the exercise, I keep hitting a wall with the __eq__()
method in my metaclass. I wish I could choose a simpler case to start Cython, but my production code isn't that simple. I cooked up a "minimal, complete example" to illustrate the problem... see the code at the bottom of the question.
Short story...
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'
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 confusing guidance...
Questions :
.pxd
files have restrictions; is defining __richcmp__()
in my .pxd
a valid way to use a .pxd
to augment pure python? .pxd
, how can I fix this to compile correctly? .pxd
augment my pure python metaclass, without re-writing the whole metaclass in a .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"]),
#Extension("car", ["car.py"]),
]
setup(
name = "really build this thing",
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
The simple answer (received from Nils Bruin via cython-users
) is that a pxd cannot be used to implement methods (such as __richcmp__()
). Since I'm using a metaclass, I need to port my code into a .pyx, so I can implement __richcmp__()
and other special cython methods.
上一篇: 来自DateTime的Julian日