为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

海绵宝宝撒 2021-08-24 18:08:13
在 IPython 中,我可以看到 Cython 类的属性是一个生成器,只需定义它然后调用:%%cythoncdef class SomeCls:    property x:        def __get__(self):            yield 1电话看起来像SomeCls().x# prints <generator at 0x102f61ee8>我在测试该属性是否为生成器时遇到问题:import typesprint(isinstance(SomeCls().x, types.GeneratorType))# prints Falseimport inspectprint(inspect.isgeneratorfunction(SomeCls.x))# prints False如何确定 Cython 类的属性是否是生成器?
查看完整描述

1 回答

?
慕桂英3389331

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


查看完整回答
反对 回复 2021-08-24
  • 1 回答
  • 0 关注
  • 180 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号