代码之家  ›  专栏  ›  技术社区  ›  Cosmo

pythoncapi:如何检查对象是否是类型的实例

  •  0
  • Cosmo  · 技术社区  · 7 年前

    instanceof . 在C/C++中,我找到了一个函数名 PyObject_IsInstance . 但似乎不是这样 isinstance .

    1. 在C++中定义了自定义类型 My . 类型定义为 MyType 对象定义是 MyObject .
    2. 添加 我的类型 到名为的导出模块 我的 .
    3. 在Python中,创建一个新实例 my = My() ,和 isinstance(my, My) 退货 True .
    4. 在C++中,我们使用 PyObject_IsInstance(my, (PyObject*)&MyType) 检查 my 0 我的 不是由定义的类的实例 我的类型 .

    完全C++代码:

    #define PY_SSIZE_T_CLEAN
    #include <python3.6/Python.h>
    #include <python3.6/structmember.h>
    #include <stddef.h>
    
    typedef struct {
        PyObject_HEAD
        int num;
    } MyObject;
    
    static PyTypeObject MyType = []{
        PyTypeObject ret = {
            PyVarObject_HEAD_INIT(NULL, 0)
        };
        ret.tp_name = "cpp.My";
        ret.tp_doc = NULL;
        ret.tp_basicsize = sizeof(MyObject);
        ret.tp_itemsize = 0;
        ret.tp_flags = Py_TPFLAGS_DEFAULT;
        ret.tp_new = PyType_GenericNew;
        return ret;
    }();
    
    // check if obj is an instance of MyType
    static PyObject *Py_fn_checkMy(PyObject *obj) {
        if (PyObject_IsInstance(obj, (PyObject *)&MyType)) Py_RETURN_TRUE;
        else Py_RETURN_FALSE;
    }
    
    static PyMethodDef modmethodsdef[] = {
        { "checkMy", (PyCFunction)Py_fn_checkMy, METH_VARARGS, NULL },
        { NULL }
    };
    
    static PyModuleDef moddef = []{
        PyModuleDef ret = {
            PyModuleDef_HEAD_INIT
        };
        ret.m_name = "cpp";
        ret.m_doc = NULL;
        ret.m_size = -1;
        return ret;
    }();
    
    PyMODINIT_FUNC
    PyInit_cpp(void)
    {
        PyObject *mod;
        if (PyType_Ready(&MyType) < 0)
            return NULL;
        mod = PyModule_Create(&moddef);
        if (mod == NULL)
            return NULL;
        Py_INCREF(&MyType);
        PyModule_AddObject(mod, "My", (PyObject *)&MyType);
        PyModule_AddFunctions(mod, modmethodsdef);
        return mod;
    }
    

    把这个编译成 cpp.so

    >>> import cpp
    >>> isinstance(cpp.My(), cpp.My)
    True
    >>> cpp.checkMy(cpp.My())
    False
    
    0 回复  |  直到 7 年前
        1
  •  2
  •   DavidW    7 年前

    METH_VARARGS

    这是典型的调用约定,其中方法的类型为PyCFunction。函数需要两个 PyObject* PyArg_ParseTuple() PyArg_UnpackTuple()

    签名的功能 Py_fn_checkMy 与此不匹配。这需要两个论点。第一个是模块,这是您要检查的内容 MyType . 第二个参数(您实际上不接受)是一个包含您传递的对象的元组。您应该从元组中提取参数并检查其类型。

    METH_O 要指定单个参数而不是从元组中提取参数,请执行以下操作:

    static PyObject *Py_fn_checkMy(PyObject *self, PyObject *obj) {
        if (PyObject_IsInstance(obj, (PyObject *)&MyType)) Py_RETURN_TRUE;
        else Py_RETURN_FALSE;
    }
    
    
    static PyMethodDef modmethodsdef[] = {
        { "checkMy", (PyCFunction)Py_fn_checkMy, METH_O, NULL },
        { NULL }
    };