Python 如何辨别PyObject的类型?

Python 如何辨别PyObject的类型?,python,Python,我正在编写一个C函数,它将PyObject*作为参数,并根据数据类型对其进行处理。例如,如果是字符串、整数、双精度、列表等 我正在寻找检查数据类型的方法,你能给我举一些例子吗 我正在使用CPython 3.8。您应该能够使用 PyObject*PyObject\u类型(PyObject*o) 当o为非空时,返回与该对象对应的类型对象 对象类型o。失败时,引发SystemError并返回NULL。 这相当于Python表达式type(o)。此函数 递增返回值的引用计数。真的没有 使用此函数而不是通

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

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


我正在使用CPython 3.8。

您应该能够使用

PyObject*PyObject\u类型(PyObject*o)

当o为非空时,返回与该对象对应的类型对象 对象类型o。失败时,引发SystemError并返回
NULL
。 这相当于Python表达式
type(o)
。此函数 递增返回值的引用计数。真的没有 使用此函数而不是通用表达式的原因
o->ob_type
,返回类型为
PyTypeObject*
的指针,除非 需要递增的引用计数


如果您想正确处理子类,您可能还需要研究一下。

Python中的大多数内置类型都有相关的类型检查函数,您可以在中查找这些函数。例如,
PyLong\u Check
检查对象是否为int(接受子类),而
PyLong\u CheckExact
执行相同的检查,但拒绝子类:

if (PyLong_Check(whatever)) {
    // do int stuff
}

还有
类型
isinstance
的C级等价物

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

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


有两种方法可以在C级别执行isinstance,具体取决于您实际需要的内容。第一个是,它完全等同于
isinstance
,包括以
isinstance
的方式处理虚拟子类和false
\uuuuuuuuuuu属性,并作为第二个参数处理类的元组。这通常不是您在C级别真正想要的,因为通过
PyObject\u IsInstance
测试并不能保证对象的内存布局

第二个是,它要求
无论什么
都是
什么类
的“具体”实例-
无论什么
的实际类型必须是
什么类
什么类
的“真实”后代。这确保了
whatever
具有实际的C级成员,即
WhateverClass
的实例

例如,使用以下类:

import abc

class A(metaclass=abc.ABCMeta):
    pass

class B: pass

A.register(B)

class C:
    __class__ = int

b = B()
c = C()
PyObject\u-IsInstance(b,A)
PyObject\u-IsInstance(c,int)
都是真的,但是
PyObject\u-TypeCheck(b,A)
PyObject\u-TypeCheck(c,int)
都是假的


特定于类型的类型检查宏,如
PyLong\u check
的行为类似于
PyObject\u TypeCheck
,而不是
PyObject\u IsInstance
。它们忽略了虚拟子类和false
\uu类
属性。

您可以使用python中的
type()
吗?答案很好。在什么情况下,您希望确保增加引用计数?这是为了防止类本身被垃圾收集吗?@flakes:与您希望增加任何其他对象的引用计数的情况完全相同:当您需要自己的新引用时,独立于原始引用。例如,如果要从正在编写的函数返回引用,通常需要确保它是新引用,而不是借用的引用。
PyObject\u IsInstance
是否会在有元类的情况下返回python级代码?如果我理解正确,您可以使用元类在python中为此实现自定义实现。这与
PyObject\u TypeCheck
不同吗?@flakes:
PyObject\u IsInstance
将调用
\uuu instancecheck\uuu
,这可能会调用Python级别的代码
PyObject\u TypeCheck
不会调用Python级别的代码。