在Cython中不使用继承共享方法实现
我在我的光线追踪器的Python绑定中有几个类,比如对象、纹理、相机等,它们都有一个叫做.transform()的方法,这个方法需要一个变换矩阵。我希望这些类也能实现.scale()、.rotate()等方法,并且能够共享一些通用的实现,这些实现会调用self.transform(...)。一种方法是从一个叫做_Transformable的类继承,这个类提供这些方法及其实现。但是Cython的“扩展类型”不支持多重继承,所以对于已经继承的类型,这种方法就行不通了。
Cython也不支持在cdef类上使用装饰器,所以像"@_transformable"这样的装饰器也不管用。而且我觉得它们也不支持 metaclasses。有没有什么好主意呢?
如果这些方法能从全局的scale()/rotate()/等函数(返回矩阵)继承它们的文档字符串,那就更好了。
编辑:这里有一段代码,给出了发生了什么的一个提示:
def translate(*args, **kwargs):
"""
Return a translation.
Accepts the same arguments that Vector(...) does.
"""
return _Matrix(dmnsn_translation_matrix(Vector(*args, **kwargs)._v))
cdef class Pigment:
"""Object surface coloring."""
cdef dmnsn_pigment *_pigment
# ...
def transform(self, Matrix trans not None):
"""Transform a pigment."""
self._pigment.trans = dmnsn_matrix_mul(trans._m, self._pigment.trans)
return self
如果用继承的方法,效果会是这样的:
cdef class _Transformable:
def scale(self, *args, **kwargs):
return self.transform(scale(*args, **kwargs))
def translate(self, *args, **kwargs):
return self.transform(translate(*args, **kwargs))
def rotate(self, *args, **kwargs):
return self.transform(rotate(*args, **kwargs))
1 个回答
0
你的可变对象可能会变成一个“万事通”。在我看来,组合是解决Cython代码和架构问题的关键。你可以看看这篇文章,里面有很好的解释。我记得,Blender就是用这种架构,所以它看起来和你想做的事情很兼容。(顺便问一下,你能贴一段代码吗?这样我可以给你一个我心中想的具体例子。)
显然,这还要看你的代码量有多大,以及你对它的控制程度。