来源:Python开发者
ID:PythonCoder
源码位置 Include/listobject.h | Objects/listobject.c
定义
typedef
struct
{
PyObject_VAR_HEAD
PyObject *
*
ob_item
;
Py_ssize_t
allocated
;
}
PyListObject
;
说明
1.
PyObject_VAR_HEAD
PyListObject
是变长对象
2.
PyObject *
*
ob_item
;
指向列表元素的指针数组
,
list
[
0
]
即
ob_item
[
0
]
3.
Py_ssize_t
allocated
;
allocated
列表分配的空间
,
ob
_
size为已使用的空间
allocated
总的申请到的内存数量
ob
_
size
实际使用内存数量
等式
:
0
结构
构造
只有一个方法
定义如下
PyObject *
PyList_New
(
Py_ssize_t
size
)
{
PyListObject *
op
;
size_t
nbytes
;
#ifdef SHOW_ALLOC_COUNT
static
int
initialized
=
0
;
if
(
!
initialized
)
{
Py_AtExit
(
show_alloc
);
initialized
=
1
;
}
#endif
// 大小为负数, return
if
(
size
0
)
{
PyErr_BadInternalCall
();
return
NULL
;
}
// 如果大小超过, 报错
/* Check for overflow without an actual overflow,
* which can cause compiler to optimise out */
if
((
size_t
)
size
>
PY_SIZE_MAX
/
sizeof
(
PyObject *
))
return
PyErr_NoMemory
();
// 计算需要的字节数(PyObject指针数组)
nbytes
=
size *
sizeof
(
PyObject *
);
// 如果缓冲池非空, 从缓冲池取
if
(
numfree
)
{
// 取缓冲池数组最后一个对象
numfree
--
;
op
=
free_list
[
numfree
];
// set refcnt=1
_Py_NewReference
((
PyObject *
)
op
);
#ifdef SHOW_ALLOC_COUNT
count_reuse
++
;
#endif
}
else
{
// 否则, GC_New分配内存空间
op
=
PyObject_GC_New
(
PyListObject
,
&
PyList_Type
);
// 分配失败
if
(
op
==
NULL
)
return
NULL
;
#ifdef SHOW_ALLOC_COUNT
count_alloc
++
;
#endif
}
// 确定ob_item列表元素指针的值
// 若大小
if
(
size
0
)
op
->
ob_item
=
NULL
;
else
{
// 分配内存
op
->
ob_item
=
(
PyObject *
*
)
PyMem_MALLOC
(
nbytes
);
if
(
op
->
ob_item
==
NULL
)
{
Py_DECREF
(
op
);
return
PyErr_NoMemory
();
}
// 初始化, 填充
memset
(
op
->
ob_item
,
0
,
nbytes
);
}
// ob_size = size
Py_SIZE
(
op
)
=
size
;
// allocated
op
->
allocated
=
size
;
// gc用
_PyObject_GC_TRACK
(
op
);
return
(
PyObject *
)
op
;
}
简化步骤
1.
判断列表缓冲池是否为空
,
是的话从缓冲池取
(
复用
)
2.
否则
,
从内存中分配空间
3.
然后初始化数据
结论
Py_SIZE
(
op
)
=
size
;
op
->
allocated
=
size
;
第一次生成
list
,
其
allocated
=
ob_size
list_resize
同时注意list_resize方法
extends
方法
,
list_resize
(
self
,
m
+
n
)
pop
方法
,
list_resize
(
self
,
Py_SIZE
(
self
)
-
1
)
append
方法
,
list_resize
(
self
,
n
+
1
)
其定义
list_resize
(
PyListObject
*
self
,
Py_ssize_t
newsize
)
{
...........
// 如果 allocated/2 <= newsize <= allocated
// 直接修改ob_size
if
(
allocated
>=
newsize
&&
newsize
>=
(
allocated
>>
1
))
{
assert
(
self
->
ob_item
!=
NULL
||
newsize
==
0
);
Py_SIZE
(
self
)
=
newsize
;
return
0
;
}
//否则
new_allocated
=
(
newsize
>>
3
)
+
(
newsize
<
9
?
3
:
6
);
new_allocated
+=
newsize
;
.............
Py_SIZE
(
self
)
=
newsize
;
self
->
allocated
=
new_allocated
;
}
即
if
allocated
/
2
<=
newsize
<=
allocated
allocated
不变
ob_size
=
newsize
else
allocated
=
newsize
+
((
newsize
>>
3
)
+
(
newsize
<
9
?
3
:
6
))
ob_size
=
newsize
回收和PyListObject对象缓冲池
看下缓冲池相关的定义
/* Empty list reuse scheme to save calls to malloc and free */
#ifndef PyList_MAXFREELIST
#define PyList_MAXFREELIST 80
#endif
// 80个
static
PyListObject *
free_list
[
PyList_MAXFREELIST
];
static
int
numfree
=
0
;
我们先看下list_dealloc的定义
static
void
list_dealloc
(
PyListObject *
op
)
{
Py_ssize
_
t
i
;
PyObject_GC_UnTrack
(
op
);
Py_TRASHCAN_SAFE_BEGIN
(
op
)
// 遍历ob_item, 释放所有类表内元素空间
if
(
op
->
ob_item
!=
NULL
)
{
/* Do it backwards, for Christian Tismer.
There's a simple test case where somehow this reduces
thrashing when a *very* large list is created and
immediately deleted. */
i
=
Py_SIZE
(
op
);
while
(
--
i
>=
0
)
{
Py_XDECREF
(
op
->
ob_item
[
i
]);
}
PyMem_FREE
(
op
->
ob_item
);
}
// 如果free_list还没满, PyListObject加入到列表中
if
(
numfree tp_free
((
PyObject *
)
op
);
Py_TRASHCAN_SAFE_END