【问题标题】:How to test if Cython property is generator?如何测试 Cython 属性是否是生成器?
【发布时间】:2019-04-24 12:16:53
【问题描述】:

在 IPython 中,我可以看到 Cython 类的属性是一个生成器,只需定义它然后调用:

%%cython
cdef class SomeCls:
    property x:
        def __get__(self):
            yield 1

电话看起来像

SomeCls().x
# prints <generator at 0x102f61ee8>

我无法测试该属性是否是生成器:

import types
print(isinstance(SomeCls().x, types.GeneratorType))
# prints False

import inspect
print(inspect.isgeneratorfunction(SomeCls.x))
# prints False

如何确定 Cython 类的属性是否是生成器?

【问题讨论】:

  • 避免在 cmets 中回答问题。
  • not 使用 cython 时,针对 types.GeneratorType 的测试工作得很好...
  • 不要挑剔从哪里获得帮助!作为一个经验丰富的发帖者,我经常用简短的 cmets 来回答。对于常规答案,我会花更多时间提供工作示例和解释。
  • 这个没有解决了这个问题,但是 Cython 现在支持标准的@property 语法(我认为现在是首选,因为它与 Python 的其余部分相匹配)。它的行为与 this 完全相同。

标签: python types generator cython isinstance


【解决方案1】:

为什么通常的方法不起作用?

首先,您可能已经知道,inspect.isgeneratorfunction(...)isinstance(..., types.GeneratorType) 之间没有区别 - 检查模块只是 calls isinstance(..., types.GeneratorType)

另一方面,types.GeneratorTypedefined as

def _g():
    yield 1
GeneratorType = type(_g())

CPython 使用 PyGenObject (here code, here documentation) 作为生成器,对于一些 ABC 类的比较没有花哨的逻辑,所以 isinstance 将归结为比较 C 对象类型。

但是,Cython 为生成器返回 __pyx_CoroutineObject(只需检查 cythonized 代码即可查看)

typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyThreadState *, PyObject *);
typedef struct {
    PyObject_HEAD
    __pyx_coroutine_body_t body;
    PyObject *closure;
    ...
    int resume_label;
    char is_running;
} __pyx_CoroutineObject;

isinstance 而言,这与 PyGenObject 无关 - 它并不真正关心 generator 是否在类型的名称中(但对于我们人类来说,这真的很令人费解,因为type(obj) 说“发电机”)。

因此,您将不得不推出自己的 isgenerator 版本,其中还考虑了 Cython 的“生成器”。有很多方法,例如

%%cython
def _f():
    yield 1
CyGeneratorType = type(_f())   
def iscygenerator(o):
    return isinstance(o, CyGeneratorType)

现在:

import inspect   
def isgenerator(o):
    return inspect.isgenerator(o)  or iscygenerator(o)

isgenerator(SomeCls().x)          #  True
iscygenerator(SomeCls().x)        #  True
inspect.isgenerator(SomeCls().x)  #  False

【讨论】:

  • 这回答了我发布的 MWE 中的问题,但不幸的是它没有解决我的问题(确定 this Spacy attribute 的类型)。但是,我可以使用您的示例设置SpacyGeneratorType = type(doc.subtree),然后针对该类型进行测试,就像您展示的那样。这主要告诉我我对 Cython 中的类型知之甚少。感谢您的帮助!
猜你喜欢
  • 2018-09-26
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-28
相关资源
最近更新 更多