我正在编写一个 C 函数,它以 PyObject* 为参数并根据数据类型进行处理。例如,如果它是一个字符串、整数、双精度浮点数、列表等等。
我正在寻找一些检查数据类型的方法,您能给我展示一些例子吗?
我使用的是 CPython 3.8。
我正在寻找一些检查数据类型的方法,您能给我展示一些例子吗?
我使用的是 CPython 3.8。
Python中的大多数内置类型都有相关的类型检查函数,你可以在文档中查找。例如,PyLong_Check
检查一个对象是否为 int(包括子类),而 PyLong_CheckExact
也执行相同的检查,但会拒绝子类:
if (PyLong_Check(whatever)) {
// do int stuff
}
type
和isinstance
的相当版本。Py_TYPE(whatever)
。这会给你一个借用引用到对象类型-它相当于访问对象的ob_type
字段。值的类型为PyTypeObject*
;如果需要,可以将其转换为PyObject*
。PyObject_Type(whatever)
。这会给你一个PyObject*
;如果需要,可以将其转换为PyTypeObject*
。(指针类型的差异与引用计数处理的差异无关)isinstance
有两种方法,具体取决于您实际想要的内容。第一种是PyObject_IsInstance(whatever, WhateverClass)
,它与isinstance
完全相同,包括处理虚拟子类和错误的__class__
属性,以及将元组作为第二个参数的处理方法。这通常不是您在C级别上真正想要的,因为通过PyObject_IsInstance
测试传递并不能保证对象的内存布局。PyObject_TypeCheck(whatever, WhateverClass)
,它要求whatever
是WhateverClass
的“具体”实例-whatever
的实际类型必须是WhateverClass
或者是一个“真正”的WhateverClass
后代。这确保了whatever
具有预期具体的C级别成员。import abc
class A(metaclass=abc.ABCMeta):
pass
class B: pass
A.register(B)
class C:
__class__ = int
b = B()
c = C()
PyObject_IsInstance(b, A)
和 PyObject_IsInstance(c, int)
都将返回 true,但是 PyObject_TypeCheck(b, A)
和 PyObject_TypeCheck(c, int)
将返回 false。
像 PyLong_Check
这样的特定类型检查宏行为类似于 PyObject_TypeCheck
,而不是 PyObject_IsInstance
。它们忽略虚拟子类和错误的 __class__
属性。
PyObject_IsInstance
如果有元类,是否会回调到 Python 级别的代码?如果我理解正确,您可以使用元类在 Python 中实现自定义实现。这与 PyObject_TypeCheck
有什么不同吗? - flakesPyObject_IsInstance
将调用__instancecheck__
,这可能会调用Python级别的代码。PyObject_TypeCheck
不会调用Python级别的代码。 - user2357112您应该能够使用PyObject_Type
PyObject* PyObject_Type(PyObject *o)
当o非
NULL
时,返回与对象o的对象类型对应的类型对象。在失败时,引发SystemError并返回NULL
。这等效于Python表达式type(o)
。此函数增加了返回值的引用计数。除非需要增加引用计数,否则没有理由使用此函数而不是常见的表达式o->ob_type
,后者返回PyTypeObject*
类型的指针。
如果您想正确处理子类,您可能还需要查看PyObject_TypeCheck
。
type()
吗? - Cresht