美文网首页
【Python】整数

【Python】整数

作者: lndyzwdxhs | 来源:发表于2018-10-26 10:49 被阅读10次

0x01 PyIntObject

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

PyIntObject对象表示一个整数(long类型的)。它是一个不可变对象,一旦创建了以后,值不能被改变。

整数是非常常见的对象。使用奇数指针表示整数可以节省很多空间,但是在特殊情况下需要贯穿整个代码来检查(Using odd pointers to represent integers would save much space but require extra checks for this special case throughout the code)。

由于一个典型的python程序需要使用很多次整数,所以就要申请和释放内存很多次,这个过程理应是非常快的。因此我们使用具有很低开销的专门的内存分配方案,而不是直接使用malloc():一个简单的专用空闲列表,在需要的时候申请内存填充这个列表。

block_list是所有PyIntBlocks对象(all PyIntBlocks)组成的单向链表,PyIntBlocks是之前申请的内存结构,链表通过节点的下一个成员连接(linked via their next members)。PyIntBlocks在系统结束(shutdown)的时候会返回给操作系统。

free_list是可以使用的PyIntObjects对象(available PyIntObjects)组成的单向链表,通过ob_type成员的滥用来连接这个链表(linked via abuse of their ob_type members)。

  • fill_free_list函数解析:申请一个新的PyIntBlock对象,存在在链表block_list的最前头;然后将PyIntObject类型的数组objects从后往前使用ob_type链接起来,组成一个链表,最后返回链表头,也就是objects数组的最后一个元素。
static PyIntObject *
fill_free_list(void)
{
    PyIntObject *p, *q;
    /* Python's object allocator isn't appropriate for large blocks. */
    p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
    if (p == NULL)
        return (PyIntObject *) PyErr_NoMemory();
    ((PyIntBlock *)p)->next = block_list;
    block_list = (PyIntBlock *)p;
    /* Link the int objects together, from rear to front, then return
       the address of the last int object in the block. */
    p = &((PyIntBlock *)p)->objects[0];
    q = p + N_INTOBJECTS;
    while (--q > p)
        q->ob_type = (struct _typeobject *)(q-1);
    q->ob_type = NULL;
    return p + N_INTOBJECTS - 1;
}
fill_free_list函数实现图解
  • 小整数初始化:python中创建整数对象的时候,如果属于小整数范围(-5~257,各个系统或版本这个范围可能不同),直接使用提前缓存的对象,不用重新创建,提高效率;每创建一个python整数对象,引用计数也会增加。
int
_PyInt_Init(void)
{
    PyIntObject *v;
    int ival;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {
              if (!free_list && (free_list = fill_free_list()) == NULL)
            return 0;
        /* PyObject_New is inlined */
        v = free_list;
        free_list = (PyIntObject *)v->ob_type;
        PyObject_INIT(v, &PyInt_Type);
        v->ob_ival = ival;
        small_ints[ival + NSMALLNEGINTS] = v;
    }
#endif
    return 1;
}

// test demon:
// test.c 
#include <stdlib.h>
#include <stdio.h>
#define NSMALLNEGINTS 5
#define NSMALLPOSINTS 257
int small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

int main()
{
    int ival;
    for(ival=-NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++){
        small_ints[ival + NSMALLNEGINTS] = ival;
    }
    for(int i=0; i<NSMALLNEGINTS + NSMALLPOSINTS; i++){
        printf("index:%d, value:%d\n", i, small_ints[i]);
    }
    return 0;
}

// 执行结果:
// ./test 
index:0, value:-5
index:1, value:-4
index:2, value:-3
index:3, value:-2
index:4, value:-1
index:5, value:0
index:6, value:1
index:7, value:2
index:8, value:3
index:9, value:4
index:10, value:5
index:11, value:6
index:12, value:7
......
  • PyIntObject创建:可以从longunicodestring类型生成PyIntObject对象,但是最后都是调用到PyObject * PyInt_FromLong(long ival)函数。先判断数值是否在小整数范围内,如果不在范围内,就从free_list中取一个PyIntObject对象,然后赋上需要创建的值
PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
#ifdef COUNT_ALLOCS
        if (ival >= 0)
            quick_int_allocs++;
        else
            quick_neg_int_allocs++;
#endif
        return (PyObject *) v;
    }
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)Py_TYPE(v);
    (void)PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

欢迎关注微信公众号(coder0x00)或扫描下方二维码关注,我们将持续搜寻程序员必备基础技能包提供给大家。


相关文章

  • Python基础知识总结

    Python 数据类型 一、整数 Python可以处理任意大小的整数,当然包括负整数,在Python程序中,整数的...

  • Python 入门篇

    一、python 变量和数据类型 1.整数 Python可以处理任意大小的整数,当然包括负整数,在Python程序...

  • (二)Python变量与数据类型

    1、Python中数据类型 1、整数 Python可以处理任意大小的整数,当然包括负整数,在Python程序中,整...

  • 3. Python3源码—整数对象

    3.1. 整数对象 整数对象是“变长对象”。 3.1.1. Python中的创建 Python中整数对象最重要的创...

  • Python第二天,数字与列表

    Python中的数字: 1.整数:在python中可对整数执行+、-、*、/运算 Python使用两个乘号表示乘方...

  • 2020-09-19

    一、python数据类型 1、int :整数。 python3唯一的整数类型,python里没有long之类的类型...

  • Python的入门

    一、python中的数据类型 1.1 整数 Python可以处理任意大小的整数,包括负整数,例如:1,100,-8...

  • Python源码学习笔记 2 整数对象

    Python中的整数类型是不可变对象,为了提高python运行效率,内部实现了小整数对象池(数组实现),和通用整数...

  • 基本数据类型

    python版本为3.5 1、国际惯例 2、基本数据类型 整数 Python可以处理任意大小的整数,当然包括负整数...

  • python学习

    python基础之数据类型和变量 一、整数 Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法...

网友评论

      本文标题:【Python】整数

      本文链接:https://www.haomeiwen.com/subject/gnpctqtx.html