如何判断 PyObject 的类型?

my_*_*ion 4 python

我正在编写一个 C 函数,它将 PyObject* 作为参数并根据数据类型对其进行处理。例如,如果它是一个字符串、一个整数、一个双精度值、一个列表等。

我正在寻找检查数据类型的方法,你能给我举一些例子吗?

我正在使用 CPython 3.8。

use*_*ica 6

Python 中的大多数内置类型都有关联的类型检查函数,您可以在docs 中查找。例如,PyLong_Check检查对象是否为 int(接受子类),并PyLong_CheckExact进行相同的检查,但拒绝子类:

if (PyLong_Check(whatever)) {
    // do int stuff
}
Run Code Online (Sandbox Code Playgroud)

还有的C级等同物typeisinstance

要在 C 中访问对象的类型,您可以使用Py_TYPE(whatever). 这为您提供了对对象类型的借用引用 - 它相当于访问对象的ob_type字段。该值的类型为PyTypeObject*; PyObject*如果需要,您可以将其转换为。

或者,如果您需要新的参考,您可以使用PyObject_Type(whatever). 这给了你一个PyObject*; PyTypeObject*如果需要,您可以将其转换为 a 。(指针类型的差异与引用计数处理的差异无关。)


isinstance在 C 级有两种方法可以做,这取决于你真正想要什么。第一个是PyObject_IsInstance(whatever, WhateverClass),它完全等同于isinstance,包括处理虚拟子类和假__class__属性的方式isinstance,以及处理类的元组作为第二个参数。这在 C 级别通常不是您真正想要的,因为通过PyObject_IsInstance测试并不能保证对象的内存布局。

第二个是PyObject_TypeCheck(whatever, WhateverClass),它要求whatever是 的“具体”实例WhateverClass- 的实际类型whatever必须是WhateverClass或 的“真实”后代WhateverClass。这确保whatever具有实例WhateverClass预期具有的实际 C 级成员。

例如,使用以下类:

import abc

class A(metaclass=abc.ABCMeta):
    pass

class B: pass

A.register(B)

class C:
    __class__ = int

b = B()
c = C()
Run Code Online (Sandbox Code Playgroud)

PyObject_IsInstance(b, A)andPyObject_IsInstance(c, int)都是真的,但是PyObject_TypeCheck(b, A)PyObject_TypeCheck(c, int)都是假的。

特定于类型的类型检查宏的PyLong_Check行为类似于PyObject_TypeCheck,而不是PyObject_IsInstance。它们忽略虚拟子类和错误__class__属性。