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

标签 python types generator cython isinstance

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

最佳答案

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

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

另一方面,types.GeneratorTypedefined as

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

CPython 使用 PyGenObject ( here codehere 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

关于python - 如何测试 Cython 属性是否为生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53420354/

相关文章:

python - 使用 Tensorflow 在 2D 张量中查找唯一值

Python subprocess communicate() yields None,当需要数字列表时

python - 在 Python 中使用 7.0 或 float(7) 是否计算量较小?

html - 我可以使用 asp FileUpload 来选择文件夹吗?

Java:将 TRUE/FALSE 的所有可能组合添加到列表中

Python 随机样本生成器(适用于庞大的人口规模)

python - 即使使用 torch.no_grad(),params 的 require_grad 也是 True

python - Kivy 中的动态网格,每个网格元素包含多个小部件

haskell - "MonadReader (Foo m) m"函数依赖导致无限类型

c# - 迭代器和枚举器的区别