Python的简单缓存

偶尔手贱敲了下交互命令

>>> a = 10
>>> b = 10
>>> a is b
True
>>> a = 1000
>>> b = 1000
>>> a is b
False
>>>

突然有点奇怪了,这可是不可变类型,尽管值一致,但是创建的应该是不同的对象,为什么会出现True呢,于是写一个弱小的code测试一下:

#!/usr/bin/env python

a = 10
b = 10

while True:
    if a is not b:
         break
    else:
        a += 1
        b += 1
print a

运行结果是257,也就是上限256,产生了一种本来认为应该创建新对象,它却没有创建新对象的假象,这是因为如此小整型会经常用到,会被缓存起来,貌似为了提高效率,python2.7整型缓存的范围是[-5, 256],不仅仅是整型,字符串也是类似

python的源码,intobject.c,可以看到大概这些内容:

#define NSMALLPOSINTS          257
#define NSMALLNEGINTS          5
/* References to small integers are saved in this array so that they
  can be shared.
  The integers that are saved are those in the range
  -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
    //如果 -5 <= ival && ival < 257, 命中缓存~
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
        return (PyObject *) v;
    }
    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);
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

python里一切皆对象,一切传递都是传递引用

一个数字对象被创建赋给a,另一个数字对象被创建赋给b,尽管两个对象保存的是同样大小的值,但实际上系统中保存的都是两个独立的对象,其中a是第一个对象的引用,b是第二个对象的引用,这里是两个不同的对象,尽管这两个对象有同样大小的数值

对象就好像一个装着内容的盒子,当一个对象被赋值到一个变量,就像是在这个盒子上贴了一个标签,表示创建了一个引用,每当这个对象有了一个新的引用,就会在盒子上新贴一张标签,当一个引用被销毁时,这个标签就会被撕掉,当所有标签都被撕掉,这个盒子就会被回收

发表评论