在Cython中不使用继承共享方法实现

0 投票
1 回答
659 浏览
提问于 2025-04-17 02:24

我在我的光线追踪器的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就是用这种架构,所以它看起来和你想做的事情很兼容。(顺便问一下,你能贴一段代码吗?这样我可以给你一个我心中想的具体例子。)

显然,这还要看你的代码量有多大,以及你对它的控制程度。

撰写回答