开发者

Sharing method implementations in Cython without inheritance

开发者 https://www.devze.com 2023-04-05 17:51 出处:网络
I have a few classes in my ray tracer\'s Python binding that implement a .transform() method (Objects, Textures, Cameras, etc.), which takes a transformation matrix.I\'d like to have all these classes

I have a few classes in my ray tracer's Python binding that implement a .transform() method (Objects, Textures, Cameras, etc.), which takes a transformation matrix. I'd like to have all these classes also implement .scale(), .rotate(), etc., and share common implementations that call self.transform(...). One way to do that would be to inherit from a _Transformable class that provides those methods and their implementations. But Cython "extension types" don't support multiple inheritence, so this doesn't work for types that already inherit.

Cython doesn't support decorators on cdef classes either, so an "@_transformable" decorator won't work either. And I don't think they support metaclasses either. Any ideas?

Bonus points if the methods can inherit their docstrings from the global scale()/rotate()/etc. functions (which return matricies).

EDIT: Here's a snippet of the file that gives an indication of what's happening:

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):
    """T开发者_Go百科ransform a pigment."""
    self._pigment.trans = dmnsn_matrix_mul(trans._m, self._pigment.trans)
    return self

The inheritance solution would look like this:

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


Your transformable is likely to become a do_everything. Composition is IMHO both the answer in term of cython code and architecture. see : this article for a good explanation. IIRC, Blender use this architecture so it looks quite compatible with what you want to do. (BTW, could you post a bit of code so I could give you an concrete example of what I have in mind).

Obviously, this depends on the size of your code base and the control you have over it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号