【问题标题】:Cython cannot refer to a declared type in a cdef class if there is a property with that same name?如果有同名的属性,Cython 不能引用 cdef 类中的声明类型?
【发布时间】:2020-02-18 16:32:14
【问题描述】:

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

对于我包装的其中一个 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


    【解决方案1】:

    最好的解决方法是

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

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

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

    (即不是 Python 行为)。


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

    【讨论】:

    • 谢谢大卫。我正在考虑修改属性名称并使用PyObject_GenericSetAttr 将它们放到类中。使用globals()['Foo'] 似乎是一个更好的主意
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多