该 存储
是“未装箱的”,但是每次访问元素时,Python都必须对其进行“装箱”(将其嵌入常规Python对象中)以便对其进行任何处理。例如,您
sum(A)遍历数组,并将每个整数一次装在一个常规Python
int对象中。那要花时间。在中
sum(L),所有装箱 *** 作均在创建列表时完成。
因此,最后,阵列通常较慢,但所需的内存却少得多。
这是最新版本的Python 3的相关代码,但是自Python首次发布以来,相同的基本思想也适用于所有CPython实现。
这是访问列表项的代码:
PyObject *PyList_GetItem(PyObject *op, Py_ssize_t i){ return ((PyListObject *)op) -> ob_item[i];}
它几乎没有什么:
somelist[i]只返回
i列表中的第一个对象(并且CPython中的所有Python对象都是指向结构的指针,该结构的初始段符合的布局
structPyObject)。
这
__getitem__是
array带有类型代码的实现
l:
static PyObject *l_getitem(arrayobject *ap, Py_ssize_t i){ return PyLong_FromLong(((long *)ap->ob_item)[i]);}
原始内存被视为平台本地
C
long整数的矢量;该
i“个
C long被读取起来;
然后
PyLong_FromLong()调用该方法将本机包装(“框”)
C long在Python
long对象中(在Python
3中,该对象消除了Python 2
int和之间的区别
long,实际上显示为type
int)。
这种装箱必须为Python
int对象分配新的内存,然后将native
Clong的位喷射到其中。在原始示例的上下文中,此对象的生存期非常短(足够长,足以
sum()将内容添加到正在运行的总计中),然后需要更多的时间来取消分配新
int对象。
这就是速度差异的来源,在CPython实现中,总是如此,而且总是如此。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)