在 Python C API 中检查一个对象是 int 还是类 int
Checking if an object is an int or int-like in Python C API
是否有类似于PyInt_Check
/PyLong_Check
的操作,考虑类型是否具有__int__
方法?
到目前为止我能找到的最接近的解决方法是
int check_int(PyObject *obj)
{
long lng;
int over;
lng = PyLong_AsLongAndOverflow(obj, &over);
if(lng == -1 && over == 0 && PyErr_Occurred()) {
PyErr_Clear();
#if PY_MAJOR_VERSION <= 2
lng = PyInt_AsLong(obj);
if(lng == -1L && PyErr_Occurred()) {
PyErr_Clear();
return 0;
}
#else
return 0;
#endif
}
return 1;
}
这里的问题是我正在有效地做类似
的事情
def isint(obj):
try:
int(obj)
except TypeError:
return False
else:
return True
但是,这是 C,我更愿意做类似的事情
def isint(obj):
return isinstance(obj, int) or hasattr(type(obj), '__int__')
我希望这样的检查已经存在,因为 PyInt_AsLong
and PyLong_AsLongAndOverflow
已经执行了它。我只想知道一个对象是否可能是一个整数,而根本不需要得到整数值。
话虽如此,我明白了实际获取值的意义,因为 hasattr(type(obj), '__int__')
实际上并不能保证对象可以合理地用作整数:例如,如果属性不是函数或者只是引发错误。在那种情况下 "no" 可能是一个有效的答案。
最接近函数的是 PyNumber_Long
, or PyNumber_Int
on Python 2。这两个函数实际上执行转换。他们还会考虑像 __trunc__
这样的方法,并将字符串转换为整数,就像从 Python-level 代码调用 int
一样。
如果要检查是否存在__int__
转换方法,可以直接查找对应的slot:
if (o->ob_type->tp_as_number and o->ob_type->tp_as_number->nb_int) {
do_whatever();
}
是否有类似于PyInt_Check
/PyLong_Check
的操作,考虑类型是否具有__int__
方法?
到目前为止我能找到的最接近的解决方法是
int check_int(PyObject *obj)
{
long lng;
int over;
lng = PyLong_AsLongAndOverflow(obj, &over);
if(lng == -1 && over == 0 && PyErr_Occurred()) {
PyErr_Clear();
#if PY_MAJOR_VERSION <= 2
lng = PyInt_AsLong(obj);
if(lng == -1L && PyErr_Occurred()) {
PyErr_Clear();
return 0;
}
#else
return 0;
#endif
}
return 1;
}
这里的问题是我正在有效地做类似
的事情def isint(obj):
try:
int(obj)
except TypeError:
return False
else:
return True
但是,这是 C,我更愿意做类似的事情
def isint(obj):
return isinstance(obj, int) or hasattr(type(obj), '__int__')
我希望这样的检查已经存在,因为 PyInt_AsLong
and PyLong_AsLongAndOverflow
已经执行了它。我只想知道一个对象是否可能是一个整数,而根本不需要得到整数值。
话虽如此,我明白了实际获取值的意义,因为 hasattr(type(obj), '__int__')
实际上并不能保证对象可以合理地用作整数:例如,如果属性不是函数或者只是引发错误。在那种情况下 "no" 可能是一个有效的答案。
最接近函数的是 PyNumber_Long
, or PyNumber_Int
on Python 2。这两个函数实际上执行转换。他们还会考虑像 __trunc__
这样的方法,并将字符串转换为整数,就像从 Python-level 代码调用 int
一样。
如果要检查是否存在__int__
转换方法,可以直接查找对应的slot:
if (o->ob_type->tp_as_number and o->ob_type->tp_as_number->nb_int) {
do_whatever();
}