Cython 元类 .pxd:我应该如何实现 `__eq__()`?
Cython Metaclass .pxd: How should I implement `__eq__()`?
我正在尝试使用 cython .pxd
来扩充现有的 python 源代码,正如 Stefan Behnel 在 "Using the Cython Compiler to write fast Python code".
的幻灯片 32 到 35 中所说明的那样
作为练习的一部分,我一直在使用元类中的 __eq__()
方法碰壁。我希望我可以选择一个更简单的案例来启动 Cython,但我的生产代码并不那么简单。我编造了一个 "minimal, complete example" 来说明问题...请参阅问题底部的代码。
短篇小说...
- 如果我使用
cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
,cython 会抱怨 Special methods must be declared with 'def', not 'cdef'
- 如果我使用
def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
,cython 会抱怨 function definition in pxd file must be declared 'cdef inline'
所以 cython 给了我令人困惑的指导...
问题:
- 我知道pure-python
.pxd
文件有限制;在我的 .pxd
中定义 __richcmp__()
是使用 .pxd
扩充纯 python 的有效方法吗?
- 如果这是使用
.pxd
的有效方法,我该如何解决才能正确编译?
- 如果这是错误的,
.pxd
可以扩充我的纯 python 元类,而无需在 .pyx
文件中重写整个元类吗? (示例:class Card
in this project)
这是我的.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)
信息性:
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
)
简单的答案(从 Nils Bruin 通过 cython-users
收到)是 a pxd cannot be used to implement methods(例如 __richcmp__()
)。因为我使用的是元类,所以我需要将我的代码移植到 .pyx 中,这样我就可以实现 __richcmp__()
和其他特殊的 cython 方法。
我正在尝试使用 cython .pxd
来扩充现有的 python 源代码,正如 Stefan Behnel 在 "Using the Cython Compiler to write fast Python code".
作为练习的一部分,我一直在使用元类中的 __eq__()
方法碰壁。我希望我可以选择一个更简单的案例来启动 Cython,但我的生产代码并不那么简单。我编造了一个 "minimal, complete example" 来说明问题...请参阅问题底部的代码。
短篇小说...
- 如果我使用
cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
,cython 会抱怨Special methods must be declared with 'def', not 'cdef'
- 如果我使用
def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
,cython 会抱怨function definition in pxd file must be declared 'cdef inline'
所以 cython 给了我令人困惑的指导...
问题:
- 我知道pure-python
.pxd
文件有限制;在我的.pxd
中定义__richcmp__()
是使用.pxd
扩充纯 python 的有效方法吗? - 如果这是使用
.pxd
的有效方法,我该如何解决才能正确编译? - 如果这是错误的,
.pxd
可以扩充我的纯 python 元类,而无需在.pyx
文件中重写整个元类吗? (示例:class Card
in this project)
这是我的.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)
信息性:
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
)
简单的答案(从 Nils Bruin 通过 cython-users
收到)是 a pxd cannot be used to implement methods(例如 __richcmp__()
)。因为我使用的是元类,所以我需要将我的代码移植到 .pyx 中,这样我就可以实现 __richcmp__()
和其他特殊的 cython 方法。