Python字符串Intern机制

Python中的字符串是经常使用的数据类型,每个字符串对象的新建和销毁都涉及到很多的资源开销。所以,在Python内部对字符串对象的处理进行了优化,其中最主要的优化就是intern机制。

字符串对象结构

在CPython源码中,字符串对象用PyStringObject表示,结构如下:

[stringobject.h]
typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];
} PyStringObject;

ob_sval是一个只有一个字符的字符数组,实际ob_sval是作为一个字符指针指向一个长度为ob_size+1个字节的内存,ob_size保存在PyObject_VAR_HEAD结构中。ob_shash是该对象的hash值,该值一般用于计算该对象作为key在hash数组中的位置。ob_sstate用于标记该对象是否被intern机制处理过。

[stringobject.h]
#define PyString_CHECK_INTERNED(op) (((PyStringObject *)(op))->ob_sstate)

Intern机制 …

查看全文 ...

Python小整数对象和大整数对象

Python在处理整数对象时,根据使用频率,将整数对象分为小整数对象和大整数对象,分别用不同的内存管理策略来处理。以下简单介绍两种方式的具体实现和运行机制是怎样的。

小整数对象

实际编程中,一些范围较小的整数会频繁使用,比如1,2,9等。如果每次对这些小整数的使用都要申请内存和释放内存,无疑会非常影响运行效率,并可能在堆上产生内存碎片。

所以Python对这类较小的整数使用了对象池技术,具体则是通过在Python中直接缓存这类对象到内存中来实现的。这类对象具体范围和具体由哪个变量来维护在源码中都有定义

[intobject.c]
#ifndef NSMALLPOSINTS
    #define NSMALLPOSINTS 257
#endif
#ifndef NSMALLNEGINTS
    #define NSMALLNEGINTS 5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS]
#endif

由源码可以看出小整数的默认范围是[-5, 257),这个范围可以根据自己的使用情况做修改。

大整数对象

Python不可能把所有范围的整数都直接缓存到内存中,所以超过小整数对象范围的数字(即大整数对象),Python使用了另外的内存管理策略 …

查看全文 ...