python内对象
在python世界中,一切都是对象,包括类也是一种对象,创建类的元类也是特殊的对象。在计算机中,一个对象实际上是一片被分配的内存空间,这些内存可能是连续的,也可能是离散的。一般来说,对象是不能静态初始化的,不能再栈空间生存,唯一的例外是类型对象,python中所有内建的类型对象都是被静态初始化的。
一旦python对象被创建,它在内存中的大小就是不变的,意味着可变对象只能在对象内维护一个指针,用于指向一块可变大小的内存区。
整数对象
在python应用程序中,整数的使用,创建,销毁非常频繁,如果是这样的话,程序的执行效率还会高吗?解决办法就是整数对象池,另外几乎所有的内建对象,都会有自己的对象缓冲池。很多小整数对象使用很频繁,那么python的做法是直接将一些小整数缓存到内存。而对于剩余的大整数来讲,python提供一块内存空间,这些内存空间由大整数轮流使用,也就是说谁需要的时候谁使用,免去了不断malloc。
字符串对象
整数属于不可变长度对象,对象创建之前,长度就已经确定,而变长对象只能在对象创建的时候才能确定长度。在python中,字符串属于变长对象中的不可变对象。可变对象维护的数据长度只能在对象创建的时候才能确定,在变长对象中,也分可变对象和不可变对象,如list和str。
同样,为了提高python的执行效率,犹如小整数对象池一样,python为字符串也设计了一个字符串缓冲池,小整数的缓冲池是在python初始化时被创建的,而字符串对象的字符串缓冲池是以静态变量的形式存在的,在python初始化完成后,缓冲池中所有PyStringObject指针都为空。
在python中为字符串提供了连接操作“+”,但是通过“+”进行字符串连接的效率极其低下。这是因为python中PyStringObject对象是一个不可变对象,当进行字符串拼接的时候,实际上必须创建一个新的PyStringObject对象,如果连接n个这样的对象,要进行n-1次内存 申请。官方推荐做法通过join方法在list或者tuple上进行连接操作,这样只用分配一次内存,大大提高效率。
List对象
在python中,PyListObject对象可以进行元素的插入删除、添加等操作,在列表中,每个元素位置存放的都是指针,用于指向一块可变大小的内存区。每次需要申请内存的时候,PyListObject总会申请一大块内存,有实际需要使用的,有空闲的一部分。python中的列表对象实际分两部分的,一个是PyListObject对象本身,二是PyListObject对象维护的元素列表,这是两块分离的内存。在创建PyListObject对象时,会首先检查缓冲池 free_lists是否有可用的对象,如果有,直接使用。
在python中,也有PyListObject缓冲池,free_lists,那么free_lists换成的对象从哪里来的呢,是什么时候创建的,答案是PyListObject对象销毁的时候。在创建一个新的list时,分两步:先创建PyListObject对象,再创建PyListObject所维护的元素列表。在删除PyListObject对象对象时,python会检查缓冲池,如果free_lists对象没满,就讲PyListObject缓存进来,下次创建的时候用。,但是这里缓存的仅仅是PyListObject,而没有这个对象曾拥有的元素列表。
dict对象
dict采用了散列表,理论上查询时时间复杂度O(1),同样,python的dict实现同样使用了缓冲池,dict查询速度很快,是以牺牲空间为代价的。相对而言,为了解决hash冲突,dict所占内存相对较大。
参考
《python源码剖析》
网友评论