1 回答

TA贡献2036条经验 获得超8个赞
为什么通常的方法不起作用?
首先,正如您可能已经知道的那样,inspect.isgeneratorfunction(...)和之间没有区别isinstance(..., types.GeneratorType)- 检查模块只是调用 isinstance(..., types.GeneratorType).
在另一方面,types.GeneratorType被定义为
def _g():
yield 1
GeneratorType = type(_g())
CPython 使用 PyGenObject(此处为代码,此处为文档)作为生成器,对于某些 ABC 类没有花哨的比较逻辑,因此isinstance将归结为比较 C 对象类型。
但是,Cython 返回一个__pyx_CoroutineObjectfor 生成器(只需检查 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;
它有没有关系PyGenObject,只要isinstance而言-它并不真正关心是否generator是在类型的名称(但对我们人类那可真是令人费解,因为type(obj)说“发电机”)。
因此,您必须推出自己的isgenerator. 有很多方法,例如
%%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
添加回答
举报