Cython:如何将Python对象作为Cython类的属性

22

我有一个现有的Python类X,我想要做以下几件事:

from my_python_module import X
cdef class Y:
    cdef X test

但是这并不能直接奏效,cdef 只能接受 C 类型,而不是 Python 类。有什么解决方法吗?

2个回答

21

我认为你不能(http://docs.cython.org/src/userguide/sharing_declarations.html#sharing-extension-types),但你可以使用__cinit__来绕过它,以确保属性具有正确的类型。扩展类型属性的声明cdef public object x有以下含义:

在您的Cython文件中(例如命名为“p.pyx”):
import my_python_module as q

cdef class Y:
    cdef int i
    cdef public object x  # public so it can be accessed from Python

    def __cinit__(self, x_):
        assert isinstance(x_, q.X)
        self.x = x_

如果您已经定义了类X,那么my_python_module.py就是您定义该类的地方:

class X(object):
    def __init__(self):
        self.i = 1

然后,你像这样使用它:
import my_python_module as q
import p

y = p.Y(q.X())
print y.x
print y.x.i

另外需要注意的是,自 cython == 0.29.22 版本起,cpdefcdef 的意思相同,并且在 cython == 3 中将不再支持(参见 Cython issue 3959,以及如果使用 cpdef 声明某个属性,则会打印出 warning that cython == 0.29.22 prints;还请参见该 Cython 版本的 changelog entry for that Cython version)。


不错,所以 object 可以用来分配任何 Python 对象? - w00d
1
@w00d:没错(http://docs.cython.org/src/userguide/language_basics.html#python-objects-as-parameters-and-return-values)。 - lbolla

1
我会使用类似这样的东西:

cdef class SomeCls:
    cdef object _x

    def __cinit__(self, x_):
        self._x = x_

    property x:
        def __get__(self):
            return self._x
        def __set__(self, x_):
            self._x = x_

当公开外部结构体或类的属性时,上述方法特别有用。请参考此处的示例: 包装C ++


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接