如何测试Cython属性是否为generator?

时间:2018-11-21 20:55:43

标签: python types generator cython isinstance

在IPython中,通过简单地定义Cython类的属性然后调用:

,我可以看到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类的属性是否是生成器?

1 个答案:

答案 0 :(得分:2)

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

首先,您可能已经知道,<template v-for="term in terms"> <label> <input type="radio" value="Yes" v-model="terms[$index].termBoolean" />Yes <input type="radio" value="No" v-model="terms[$index].termBoolean" />No </label><br> </template> inspect.isgeneratorfunction(...)之间没有区别-检查模块只是calls isinstance(..., types.GeneratorType)

另一方面,isinstance(..., types.GeneratorType)defined as

types.GeneratorType

CPython将PyGenObject(here codehere documentation)用于生成器,对于某些ABC类,没有比较理想的逻辑,因此def _g(): yield 1 GeneratorType = type(_g()) 可以归结为比较C对象类型。

但是,Cython会为生成器返回一个__pyx_CoroutineObject(只需查看经过Cythonized验证的代码即可)

isinstance

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; 而言,它与PyGenObject无关-它实际上并不在乎isinstance是否是类型名称(但对于我们人类来说,它是可能确实令人困惑,因为generator表示“发电机”。

因此,您必须推出自己的type(obj)版本,该版本还考虑了Cython-“ generators”。有很多方法,例如

isgenerator

现在:

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