python - Cython 元类.pxd : How should I implement `__eq__()` ?

标签 python cython metaclass

我正在尝试使用 cython .pxd 来扩充现有的 python 源代码,正如 Stefan Behnel 在 "Using the Cython Compiler to write fast Python code" 的幻灯片 32 到 35 中所说明的那样.

作为练习的一部分,我一直在使用元类中的 __eq__() 方法碰壁。我希望我可以选择一个更简单的案例来启动 Cython,但我的生产代码并不那么简单。我编写了一个“最小的完整示例”来说明问题......请参阅问题底部的代码。

短篇小说...

  • 如果我使用 cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):,cython 提示说 特殊方法必须用 'def' 声明,而不是 'cdef '
  • 如果我使用 def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):,cython 会提示 pxd 文件中的函数定义必须声明为“cdef inline”

所以 cython 给了我令人困惑的指导......

问题:

  • 我知道纯 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)

汽车.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))

设置.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
)

最佳答案

简单的答案(通过 cython-users 从 Nils Bruin 收到)是 a pxd cannot be used to implement methods (例如 __richcmp__())。因为我使用的是元类,所以我需要将我的代码移植到 .pyx 中,这样我就可以实现 __richcmp__() 和其他特殊的 cython 方法。

关于python - Cython 元类.pxd : How should I implement `__eq__()` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28023151/

相关文章:

python - 使用请求库获取 cookie 过期时间

python - 不使用浏览器登录 Facebook

python - 如何释放类型化的 numpy 数组?设置 callback_free_data 是一个可行的选择吗?

python - 使用元类来跟踪 python 中的实例

python - 删除现有的类变量 yield AttributeError

python - 具有 __init_subclass__ 和可子分类注册表的注册表模式

python - 如何使用纯 python 脚本更新/升级 linux 机器

python - 圆计算器无法正常工作

python - 在 Cython 中将复杂的 numpy 数组传递给 C++

c++ - Cython 包装 operator<< 来自多个命名空间