Próbuję rozszerzyć istniejące źródło python o cython .pxd
, jak Stefan Behnel ilustruje na slajdach od 32 do 35 z "Using the Cython Compiler to write fast Python code".Metaclass Cython .pxd: Jak powinienem wdrożyć `__eq __()`?
W ramach ćwiczenia uderzam w ścianę metodą __eq__()
w metaclassie. Chciałbym móc wybrać prostszy przypadek, aby uruchomić Cython, ale mój kod produkcyjny nie jest taki prosty. Przygotowałem "minimalny, kompletny przykład", aby zilustrować problem ... zobacz kod na dole pytania.
Krótka historia ...
- Jeśli używam
cdef inline __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
, Cython zarzucaSpecial methods must be declared with 'def', not 'cdef'
- Jeśli używam
def __richcmp__(Japan_Car_ABC self, Japan_Car_ABC other, int op):
, Cython zarzucafunction definition in pxd file must be declared 'cdef inline'
Więc Cython daje mi mylące wskazówki ...
Pytania:
- wiem, że pure-python
.pxd
pliki mają ograniczeń; definiuje__richcmp__()
w moim.pxd
prawidłowy sposób korzystania z.pxd
w celu wzmocnienia czystego Pythona? - Jeśli jest to prawidłowy sposób korzystania z
.pxd
, jak mogę to naprawić, aby poprawnie skompilować? - Jeśli jest to błędne, czy
.pxd
może wzbogacić mój czysty metaklak Pythona, bez ponownego zapisywania całego metaklasu w pliku.pyx
? (Przykład:class Card
in this project)
To jest mój .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)
informacyjne:
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
)