再Python中创建一个元组时,本质上就是创建一个结构体对象。
元组的核心结构体简化后如下:
typedef struct{ struct _object *_ob_next; struct _object *_ob_prev; //双向环状链表中上一个和下一个,python内部将对象 Py_ssize_t ob_refcnt; //引用计数器,即:有多少变量使用了这个列表对象放到链表中便于进行内存管理 Py_ssize_t ob_size; //元素个数 pyObject *ob_item[1]; //存储元组中的元素 [指针,]}PyTupleObject;
*ob_item[1]是只有一个元素的指针数组,怎么存储元素中的多个元素呢?
1.创建元组
v1 = tuple()v2 = tuple(['amy','alex','davID'])
1.1 空元组
内部源码的执行过程如下:
1.2 非空元组
1.2.1 元组转换为元组
因为元组创建开辟内存的过程中,会检查元组中元素,如果元素本身就是元组,就会直接返回元素的内存地址。
1.2.2 列表转换为元组
如果元组里面是列表,会检查元组中元素,如果元素本身就是元组,就会直接返回元素的内存地址。
1.2.3 迭代器转换为元组(或可迭代对象)
如果元组里面是迭代器,会先猜想它的元素个数,然后根据猜想个数创建元组的结构体对象(开辟内存),再将迭代器的每个元素放到元组中(放的过程中,会进行判断猜想数字是否正确,如果猜小了会扩容(原长度*0.25+2.5),猜大会进行缩容。)。
2.切片取值
(1)执行过程:元组切片只拷贝元组结构体,不拷贝数据。切片过程是根据切片的元素个数,创建元组(开辟内存),然后再将原来元组中的元素指针(地址)复制给元组。
3.销毁&缓存(只缓存元素个数20个以内的)
v1 = ('amy','davID','bob')v2 = (11,22,3,44)del v1 //引用计数器减一置为0del v2
元组的删除并非真正删除,会缓存起来(存在对应的free_List里),如果下一次出现相同数量元组,会进行利用。
三个元素存3,四个元素存4,根据元素个数存到对应free_List,并且num_free变为1
销毁两个相同元素个数的元组时,根据后来居上原则,将后来的元组地址缓存到对应的free_List中,而先来的元组地址存到后来元组的ob_item的第一个位置中。并且num_free变为2.
如果此时创建新的相同元素元组时,会将(11,22,33)拿走,并且num_free变为1。
3.1 空元组
3.2 非空元组
(1)为什么元组内存地址一样?
(2)为什么元组转换为元组内存地址一样?
因为元组创建开辟内存的过程中,会检查元组中元素,如果元素本身就是元组,就会直接返回元素的内存地址。
(3)为什么列表转换为元组,元素的内存地址是一样的?
如果元素本身是列表,会循环列表中每一个元素,将列表中的元素的指针(地址)赋值给元组
(4)迭代器转换为元组(或可迭代对象)
如果是迭代器或者可迭代对象,则先猜想它长度,一般是10,如果长度不够则扩容(原长度*0.25+2.5),长度超了则缩容。然后再去创建元组结构体对象,再将迭代器中的每个元素放到元组中,
内部有缓存则优先去缓存中获取对应个数的free_List。
(5)为什么销毁元组后,再创建元组内存地址有时相同,有时不相同?
因为销毁的元组个数可能相同,排在前一个元组的和创建的元组个数相同,但并不是之前销毁的,故地址不同,相反则相同。
(6)元组删除缓存范围?
0-2000
(7)元组缓存限制有哪些?
元素个数20以内、缓存个数2000以内
(8)元组创建流程是什么?
对于空元组,其一创建就缓存到free_List[0]中。(故空元组地址都是一样的)
对于非空元组,如果本身就是元组,则直接返回原来元组内存地址;(元组转元组)
如果是列表,不拷贝数据本身,而是将列表中的元素地址放到元组对应的ob_item中;(列表转元组)
如果是迭代器或者可迭代对象,则先猜想它长度,一般是10,如果长度不够则扩容(原长度*0.25+2.5),长度超了则缩容。然后再去创建元组结构体对象,再将迭代器中的每个元素放到元组中,
内部有缓存则优先去缓存中获取对应个数的free_List。(迭代器转为元组)
(9)创建两个元组并进行销毁,随后再创建两个元组,第一个元组跟第二个销毁元组内存地址一样,第二个元组地址为什么和第一个元组地址不一样?
因为创建的第一个元组拿到第二个销毁元组地址后,pyhon内部会销毁元组,然后排到了第一个销毁元组前面,所以第二个创建的元组地址虽然也从free_List中获取内存地址,
但并不是原第一个销毁元组地址。
总结
以上是内存溢出为你收集整理的Python元组底层剖析(缓存机制)及面试题全部内容,希望文章能够帮你解决Python元组底层剖析(缓存机制)及面试题所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)