python - Python C API:如何检查对象是否是类型的实例
问题描述
我想检查一个对象是否是某个类的实例。在 Python 中,我可以使用instanceof
. 在 C/C++ 中,我发现了一个名为PyObject_IsInstance的函数。但它似乎不像isinstance
.
详细(也描述为下面的示例代码):
- 在 C++ 中,我定义了我的自定义类型
My
。类型定义为MyType
,对象定义为MyObject
。 - 使用名称添加
MyType
到导出的模块My
。 - 在 Python 中,创建一个新实例
my = My()
,然后isinstance(my, My)
返回True
。 - 而在 C++ 中,我们使用
PyObject_IsInstance(my, (PyObject*)&MyType)
来检查my
,并且返回0
,这意味着my
它不是由 定义的类的实例MyType
。
完整的 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
,并在 Python 中进行测试:
>>> import cpp
>>> isinstance(cpp.My(), cpp.My)
True
>>> cpp.checkMy(cpp.My())
False
解决方案
这是典型的调用约定,其中方法的类型为 PyCFunction。该函数需要两个
PyObject*
值。第一个是方法的 self 对象;对于模块函数,它是模块对象。第二个参数(通常称为 args)是一个表示所有参数的元组对象。此参数通常使用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 }
};
推荐阅读
- r - 如何在 xts 对象中选择每年的最后一次观察
- sas - Proc PLM 无法使用 Proc Reg 输出 (SAS) 创建置信区间
- css - 引导网格在动态宽度容器中不起作用
- linux - 了解设备驱动程序读写函数中的指针
- apache - 使用 app.domain.se 中 sub1.domain.com 中的文件
- node.js - 纱线服务错误命令失败,退出代码为 1
- javascript - 如何将缩小的 js 文件合并到 ASP.NET MVC 应用程序
- mysql - 如何选择单元格为空的最后一行
- php - 如何在 OOP 单例中将参数传递给 add_feed
- python - 类架构:Python中内部类和外部类的循环依赖