Cython Metaclass .pxd:我应该如何实现`

我正在尝试用cython .pxd扩充现有的python源.pxd ,正如Stefan Behnel在“使用Cython编译器编写快速Python代码”幻灯片32到35中所说明的那样。

作为练习的一部分,我使用元类中的__eq__()方法继续打墙。 我希望我可以选择一个更简单的例子来启动Cython,但是我的生产代码并不那么简单。 我制作了一个“最小的完整示例”来说明问题......查看问题底部的代码。

短篇故事...

  • 如果我使用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'中的function definition in pxd file must be declared 'cdef inline'
  • 所以cython给了我混乱的指导......

    问题

  • 我知道纯python .pxd文件有限制; 在我的.pxd定义__richcmp__()是一种使用.pxd来扩充纯python的有效方法?
  • 如果这是一个使用.pxd的有效方法,那我该如何解决这个问题才能正确编译?
  • 如果这是错误的, .pxd是否可以扩充我的纯Python元类,而不需要在.pyx文件中.pyx整个元类? (例如:此项目中的class Card
  • 这是我的.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
    )
    

    简单的答案(通过cython-users从Nils Bruin获得)是一个pxd不能用来实现方法(比如__richcmp__() )。 由于我使用的是元类,因此我需要将我的代码移植到.pyx中,以便实现__richcmp__()和其他特殊的cython方法。

    链接地址: http://www.djcxy.com/p/24285.html

    上一篇: Cython Metaclass .pxd: How should I implement `

    下一篇: AuthorizationError when confirming SNS subscription over HTTP