第一章 python的内建对象
python中一切都是对象。在PyIntObject中定义了很多函数指针,这些函数指针对应着类型对象所定义的操作。其中有三组非常重要的操作族,tp_as_number, tp_as_sequence, tp_as_mapping,分别对应着PyNumberMethods, PySequenceMethods, PyMappingMethods函数族,这三个函数都是分别定义着一个整数对象、序列对象、关联对象应该有的一些操作。在python中对于任何一种类型来说,都可以同时定义三个函数族中的所有操作,也就是说,我们可以在继承python固有的类型时,又同时重写python的special method,从而实现我们自己定义的特殊类型。比如可以实现一个对象,既可以表现出数值特性,也可以表现出关联对象的属性。
第二章 python中的整数对象
python的整数对象。在python中会有一个整数对象池,里面维护着-5到256之间的整数,当我们需要使用这些范围的数字时,直接到对象池中去提取。这样设计是因为在实际的开发中,这些小数可能会被频繁的使用,频繁的创建和湮灭会导致效率非常低。对于超出这些范围的数字,python底层则是通过单独申请一块内存块来给这些大整数轮流使用,当某个对象的引用次数为零的时候,会把该对象所占用的这块内存添加到空闲区(注意,这里python并没有将释放的内存还给系统,所以当出现很多大数要被使用的时候,而这些数又是使用一次,可能就会占用系统的所有内存。)
第三章 python中的字符串对象
- 在python中,PyStringObject是字符串对象的实现,它是一个可变长度内存的对象,同时又是一个不可变对象(字符串定义之后不可再改变)。python字符串对象中的intern机制,类似于前面的python整数对象池。其关键是在于在系统中有一个(key, value)的映射关系集合,集合名字叫做Intered。在这个集合中记录过被intern机制处理过的字符串。当python在创建一个字符串时,首先会建立一个PyStringObject对象a,然后利用intern机制处理,如果当前这个字符串对象已经在interned中存在,记为b,则将指向a的对象的指针指向b,然后intern机制会将对象a的引用计数减为0而被销毁。这样的话,可以达到减少内存的目的。
也许会有一个问题,为什么一定要先创建一个临时PyStringObject对象呢?
这是因为intern机制只能应用在PyStringObject对象之上,别的任何对象都不可以。因此这里必须要先创建一个临时对象。 - python中也为一个字节的字符设计了字符缓冲池,与小整数对象池不一样的是,小整数对象池在python初始化的时候就会被创建,而字符串对象中的字符缓冲池是以静态变量形式存在的,在python初始化完成之后,字符缓冲池是空的。当python在创建一个PyStringObject的时候,如果字符串长度为1(即单个字符串),则将会对这个字符进行intern操作,将intern的这个结果缓存到字符缓冲池中。当通过PyString_FromStringandSize(const char *str, int size)来创建字符对象时,如果size等于1,并且在字符缓冲池中存在,则直接返回。
- python中字符串的连接效率问题。当我们采用+号来连接多个字符串时,效率是非常低的。其根源在于,python中的字符串对象是一个不可变对象,因此在连接两个字符串的时候,则要去新建一个PyStringObject对象,当我们用‘+’来连接N个字符串时,实际上会进行N-1次内存申请和内存搬运,因而效率很低。解决方案是,我们采用字符串对象的join操作来实现多个字符串的连接,当使用join操作的时候,会一次性计算好需要的总的内存,也就是只需要执行一次内存申请,因此效率会比用‘+’号连接的效率更高
strs_list = ['hello', 'fay', 'welcome', 'to', 'python ']
' '.join(strs_list)