浅析 Python3 列表操作之 * 和 *=
初学 Python 时总是会将a*=n
理解为a=a*n
,稍微深入后就会知道在 Python 中的不同,其中*
调用__mul__
,而*=调用__imul__
。
对于 list 对象也支持乘法操作,截止到 Python3.7 版本,上述仍然是成立的。我们知道 list 是由 C 实现的,所以真正的底层调用肯定也是 C 的实现。观察 list 对象的 C 实现的源码我们会知道乘法*
操作调用list_repeat
,*=
会调用list_inplace_repeat
,下面分别看一下两者的 C 实现方式。
▍* 调用 list_repeat
从以上可以看出,list_repeat
方法需要多少空间就申请多少空间,该操作返回的一个新的列表对象。
▍*= 调用 list_inplace_repeat
list_inplace_repeat
代码中通过调用list_resize
来进行扩容,并告诉它这个列表需要容纳size*n
个元素。从list_resize
代码来看,当allocated
空间足够时,不会进行扩容操作。
新申请的空间总是比所需要的大的。如果进行 pop 等减小 list 元素数量的操作来看,实际上列表的大小也会按照相应策略进行缩减操作。
If the newsize falls lower than half the allocated size, then proceed with the realloc() to shrink the list.
--- From cpython
▍总结
*=
会调用list_resize
,可能会引起 list 空间扩容的情况,而且此时 list 对象占用空间会比实际 list 对象中元素占用空间大。*
会按需获取申请空间大小,不会调用list_resize
方法。
好好学习,天天向上!
版权声明: 本文为 InfoQ 作者【王坤祥】的原创文章。
原文链接:【http://xie.infoq.cn/article/718a9ebb2a55f8f21e6a7a824】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论