鱼C论坛

 找回密码
 立即注册
查看: 1686|回复: 1

[技术交流] 关于Python底层整数类型实现的问题

[复制链接]
发表于 2021-1-24 16:07:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Python版本号 3.8.6

在阅读Python源码的时候,关于整数类型的实现,我有点小疑惑。
简单看一下小整数的实现(完整代码在最下面),在for循环里,首先看到第一句
  1. size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
复制代码

这里面size会根据ival的正负来分别取-1/0/1。然后是进行引用计数的更新(由于小整数是一定会天地同寿的这里就不分析了)。
接下来可以看到,代码中的这两行
  1. Py_SIZE(v) = size;
  2. v->ob_digit[0] = (digit)abs(ival);
复制代码

第二行很显然是把ival对应值取绝对值以后送到存储空间中,但是第一行我就觉得不是特别懂,因为size在这里很显然是ival的符号,但是却赋给了v的size。

进一步地,我看到Py_SIZE的实现
  1. typedef struct {
  2.     PyObject ob_base;
  3.     Py_ssize_t ob_size; /* Number of items in variable part */
  4. } PyVarObject;

  5. /* Cast argument to PyVarObject* type. */
  6. #define _PyVarObject_CAST(op) ((PyVarObject*)(op))

  7. #define Py_SIZE(ob)             (_PyVarObject_CAST(ob)->ob_size)
复制代码

可以看到,这个Py_SIZE(ob)是将ob->ob_size赋值的一个宏定义。而ob_size对应的是类的元素个数,如果传入一个负值或者0,这个地方岂不是很离谱?还是说Python底层实现的时候对于整数类型的这个地方有什么特殊的处理?

以下是详细代码

  1. # longobject.c
  2. int
  3. _PyLong_Init(void)
  4. {
  5. #if NSMALLNEGINTS + NSMALLPOSINTS > 0
  6.     int ival, size;
  7.     PyLongObject *v = small_ints;

  8.     for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {
  9.         size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
  10.         if (Py_TYPE(v) == &PyLong_Type) {
  11.             /* The element is already initialized, most likely
  12.              * the Python interpreter was initialized before.
  13.              */
  14.             Py_ssize_t refcnt;
  15.             PyObject* op = (PyObject*)v;

  16.             refcnt = Py_REFCNT(op) < 0 ? 0 : Py_REFCNT(op);
  17.             _Py_NewReference(op);
  18.             /* _Py_NewReference sets the ref count to 1 but
  19.              * the ref count might be larger. Set the refcnt
  20.              * to the original refcnt + 1 */
  21.             Py_REFCNT(op) = refcnt + 1;
  22.             assert(Py_SIZE(op) == size);
  23.             assert(v->ob_digit[0] == (digit)abs(ival));
  24.         }
  25.         else {
  26.             (void)PyObject_INIT(v, &PyLong_Type);
  27.         }
  28.         Py_SIZE(v) = size;
  29.         v->ob_digit[0] = (digit)abs(ival);
  30.     }
  31. #endif
  32.     _PyLong_Zero = PyLong_FromLong(0);
  33.     if (_PyLong_Zero == NULL)
  34.         return 0;
  35.     _PyLong_One = PyLong_FromLong(1);
  36.     if (_PyLong_One == NULL)
  37.         return 0;

  38.     /* initialize int_info */
  39.     if (Int_InfoType.tp_name == NULL) {
  40.         if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
  41.             return 0;
  42.         }
  43.     }

  44.     return 1;
  45. }
复制代码





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-1-24 18:59:18 | 显示全部楼层
你应该发到 C语言交流里
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-28 22:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表