2015-01-19 16 views
7

Stefan Behnel, "Using the Cython Compiler to write fast Python code"'un 32-35 arası slaytlarında gösterildiği gibi, varolan bir python kaynağını .pxd numaralı bir cython ile artırmaya çalışıyorum.Cython Metaclass .pxd: __eq __() `yi nasıl uygulamalıyım?

Egzersizin bir parçası olarak, metaclassımda __eq__() yöntemiyle bir duvara çarpıyorum. Cython'u başlatmak için daha basit bir vaka seçebilseydim, ama üretim kodum bu kadar basit değil. Sorunu göstermek için "minimal, tam bir örnek" hazırladım ... sorunun alt kısmındaki kodu görün. Ben cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op): kullanırsanız

Kısa hikaye ...

  • , Cython ben def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op): kullanırsanız Special methods must be declared with 'def', not 'cdef'
  • , Cython function definition in pxd file must be declared 'cdef inline'

Yani Cython bana verir şikayet şikayet kafa karıştırıcı rehberlik ...

Sorular:

  • saf-piton .pxd dosya kısıtlamaları olduğunu biliyoruz; .pxd'umdaki __richcmp__()'u .pxd nolu saf pythonu artırmak için geçerli bir yol tanımıyor mu?
  • .pxd'u kullanmanın geçerli bir yolu buysa, bunu doğru şekilde derlemek için nasıl düzeltebilirim?
  • Eğer bu doğru değilse, .pxd, .pyx dosyasında tüm meta sınıfı yeniden yazmadan, saf python metaclassmı artırabilir mi? (Örnek: class Card in this project):

    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

Bu

### 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) 

Bilgi ... benim .pxd olduğunu :

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 
) 

cevap

3

(cython-users ile Nils Bruin alınan) basit bir cevap pxd (örneğin __richcmp__() gibi) yöntemleri uygulamak için kullanılamaz olmasıdır. Bir metaclass kullanıyorum, kodumu bir .pyx içine yerleştirmem gerekiyor, bu yüzden __richcmp__() ve diğer özel sshon yöntemlerini uygulayabiliyorum.