下划线前缀在 C API 中的含义与普通 Python 中的含义大致相同:“此函数是一个可能会更改的实现细节,所以如果你使用它,请注意自己”。不禁止您使用此类功能,如果这是实现特定目标的唯一方法(例如,在您的情况下显着提高效率),那么只要您意识到危险,就可以使用 API。
如果_PyLong_FromByteArray
API 是真正私有的,那么它将是一个static
函数,不会被完整记录并以longobject.h
. 事实上,Tim Peters(著名的 Python 核心开发者)明确地祝福它的使用:
[丹克里斯滕森]
我和我的学生正在编写一个 C 扩展,它会生成一个大的二进制整数,我们希望将其转换为 python long。位数可能远远超过 32 甚至 64。我的学生在 longobject.h 中找到了函数 _PyLong_FromByteArray,这正是我们所需要的,但前导下划线让我很警惕。使用此功能是否安全?
Python 在内部使用它,所以最好是 ;-)
它会继续存在于未来版本的 python 中吗?
没有保证,这就是为什么它有一个前导下划线:它不是官方支持的、外部记录的、广告 Python/C API 的一部分。碰巧我添加了该函数,因为 Python 在内部需要跨不同 C 模块的某种形式的功能。将其作为 Python/C API 的官方部分需要做更多的工作(我没有时间去做),并且会产生一个永恒的新维护负担(无论如何我都不热衷 ;-))。
在实践中,很少有人接触 Python 实现的这一部分,所以我不/期望/它会在未来几年内消失,甚至改变。我能想到的最大的不安全感是,有人可能会发起一场运动,以基于表示负整数的不同方式使其他一些字节数组 <-> 长接口“正式”。但即便如此,我仍希望当前的非官方函数保留,因为
struct
模块的“q”格式和pickle
模块的协议 = 2 长序列化格式仍然需要 256 的补码表示。
还是我们应该使用其他方法?
不,这就是为什么发明这些功能的原因 ;-)
这是文档(来自 Python 3.2.1):
/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in
base 256, and return a Python long with the same numeric value.
If n is 0, the integer is 0. Else:
If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB;
else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the
LSB.
If is_signed is 0/false, view the bytes as a non-negative integer.
If is_signed is 1/true, view the bytes as a 2's-complement integer,
non-negative if bit 0x80 of the MSB is clear, negative if set.
Error returns:
+ Return NULL with the appropriate exception set if there's not
enough memory to create the Python long.
*/
PyAPI_FUNC(PyObject *) _PyLong_FromByteArray(
const unsigned char* bytes, size_t n,
int little_endian, int is_signed);
它是“下划线前缀”API 的主要原因是因为它依赖于 Python 的实现,long
作为以 2 为基数的单词数组。这不太可能改变,但由于您在此基础上实现了一个 API,您可以将调用者与以后 Python API 中的更改隔离开来。