首页 > 解决方案 > 如果有同名的属性,Cython 不能引用 cdef 类中的声明类型?

问题描述

我有一些包含 C++ 库的复杂生成的 cython 代码。

对于我包装的其中一个 C++ 库,我遇到了一个非常难以理解的错误。以下是一个最小的可重现示例

bad.pxd

cdef class Foo:
    pass

cdef class Bar:
    pass

bad.pyx

cdef class Bar:
    x = {}

    Bar.x['Foo'] = Foo

    @property
    def Foo(self):
        pass

    @Foo.setter
    def Foo(self, val):
        pass

来自 cython 编译器的错误:

Error compiling Cython file:
------------------------------------------------------------
...
cdef class Bar:
    x = {}

    Bar.x['Foo'] = Foo
                ^
------------------------------------------------------------

bad.pyx:4:19: 'Foo' is not a constant, variable or function identifier

如果我注释掉Bar.x['Foo'] = Foo或注释掉属性,这编译得很好。

如果您还将该名称用作属性,则似乎无法引用该类型名称。如果它是一种方法,而不是属性,那么这样做似乎是可以的。

这是否违反了 Cython 中的某些规则,或者这更可能是一个错误?

我意识到正确的答案是“不要那样做”,但不幸的是,我无法控制导致这个公认的奇怪类定义的名称。

标签: cython

解决方案


最好的解决方法是

Bar.x['Foo'] = globals()['Foo'].

即使在您提到工作的某些情况下,它们也不会像您期望的那样做:如果Foo是一种方法,那么 dict 最终会是:

{'Foo': <method 'Foo' of 'modulename.Bar' objects>}

(即不是 Python 行为)。


这可能是一个错误,但我怀疑修复它是否容易或优先级高,因为它是在编译时解决查找和属性不可分配的组合。前者几乎可以肯定是已知的并且可能无法修复。可以在问题跟踪器上报告错误。


推荐阅读