如何测试 Cython 属性是否为生成器?

在 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 类的属性是否是生成器?


海绵宝宝撒
浏览 181回答 1
1回答

慕桂英3389331

为什么通常的方法不起作用?首先,正如您可能已经知道的那样,inspect.isgeneratorfunction(...)和之间没有区别isinstance(..., types.GeneratorType)- 检查模块只是调用 isinstance(..., types.GeneratorType).在另一方面,types.GeneratorType被定义为def _g():&nbsp; &nbsp; yield 1GeneratorType = type(_g())CPython 使用 PyGenObject(此处为代码,此处为文档)作为生成器,对于某些 ABC 类没有花哨的比较逻辑,因此isinstance将归结为比较 C 对象类型。但是,Cython 返回一个__pyx_CoroutineObjectfor 生成器(只需检查 cythonized 代码即可查看)typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyThreadState *, PyObject *);typedef struct {&nbsp; &nbsp; PyObject_HEAD&nbsp; &nbsp; __pyx_coroutine_body_t body;&nbsp; &nbsp; PyObject *closure;&nbsp; &nbsp; ...&nbsp; &nbsp; int resume_label;&nbsp; &nbsp; char is_running;} __pyx_CoroutineObject;它有没有关系PyGenObject,只要isinstance而言-它并不真正关心是否generator是在类型的名称(但对我们人类那可真是令人费解,因为type(obj)说“发电机”)。因此,您必须推出自己的isgenerator. 有很多方法,例如%%cythondef _f():&nbsp; &nbsp; yield 1CyGeneratorType = type(_f())&nbsp; &nbsp;def iscygenerator(o):&nbsp; &nbsp; return isinstance(o, CyGeneratorType)现在:import inspect&nbsp; &nbsp;def isgenerator(o):&nbsp; &nbsp; return inspect.isgenerator(o)&nbsp; or iscygenerator(o)isgenerator(SomeCls().x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #&nbsp; Trueiscygenerator(SomeCls().x)&nbsp; &nbsp; &nbsp; &nbsp; #&nbsp; Trueinspect.isgenerator(SomeCls().x)&nbsp; #&nbsp; False
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python