python 源码解析读书笔记(一)——内置对象

# 现场录音视频

1.类型的类型

obj int(10).ob_type -> PyInt_Type
PyInt_Type.ob_type -> PyType_Type
PyInt_Type.tp_base -> PyBaseObject_Type
PyBaseObject_Type.ob_type -> PyType_Type
PyType_Type.ob_type -> PyType_Type

更精确的参考源码解析262页图。

2.小整数对象

if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
    v = small_ints[ival + NSMALLNEGINTS];
    Py_INCREF(v);
}

3.大整数对象,空对象池,对象缓存

>>> a = 1000000
>>> b = 2000000
>>> id(a) == id(1000000)
False
>>> id(100000) == id(100000)
True

最后一个是因为python解析器在解析对象的时候,对前后生成的对象进行了缓存。经过测试,对文件也有效。

4.字符串对象复用和缓存

>>> c = 'qazwsxedcrfvt'
>>> c += 'gbyhnujmikolp'
>>> a = 'qazwsxedcrfvtgbyhnujmikolp'
>>> id(a) == id(c)
False
>>> a = 'abc'
>>> b = 'def'
>>> c = 'abc'
>>> id(a) == id(c)
True
>>> b = 'abcde'
>>> id(b[1]) == id(c[1])
True

缓存原理同上,对于长度为0, 1的小字符串,永久缓存。

5.free_list对象缓存的机制

每个类别有自己的free_list对象,用于缓存已经被销毁的对象。目前尚不清楚GC是否会定时释放这部分内存,但是python在对象引用到0时是不释放对象的,而且多数情况下表现为内存泄漏。而且多种对象的free_list不能互相通用,继承子类也不适用。

6.list对象的行为

list对象用一种vector等同的方法处理对象池。因此随机插入(尤其是头部插入)一个对象超长队列会引发大量的内存复制行为。

7.dict对象的索引方案

dict对象的索引方案使用的是哈希表,而且是开放地址法的哈希表。当装载率达到一定规模后,会新申请一块内存,将有效数据复制过去。最小的表空间为8个对象,当装载率超过2/3时,会扩大规模到当前active的4倍(超过50000个对象为2倍)。目前为止,在对象被删除后,其表空间并不释放。因此曾经增长的非常大的dict对象,可以定期复制以回收空间。

8.dict的用法注释

从序列中移除重复对象

dict.fromkeys(seqn).keys()

计算序列中元素出现次数

for e in seqn: d[e] = d.get(e,0) + 1

词典中移除大量元素

d = dict([(k, v) for k, v in d.items() if k != xxx])

词典中访问可能不存在的元素(当不存在的风险高于5%时)

o = d.get(k, default)

词典中访问可能不存在的元素(当不存在的风险低于5%时)

try: o = d[k]
except KeyError: o = default

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。