- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python源码解析之List由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
创建列表C语言底层的结构体 。
1
2
3
4
|
lists
=
[]
list
.append(
'name'
)
list
.append(
'age'
)
list
.append(
'grade'
)
|
1
2
3
4
5
6
7
8
|
typedef struct{
struct _object
*
_ob_next;
struct _object
*
_ob_prev;
/
/
python内部将对象放在链表进行内存管理
Py_ssize_t ob_refcnt;
/
/
引用计数器,就是多少变量用了它
PyObject
*
*
ob_item;
/
/
指针的指针,存列表的元素
Py_ssize_t ob_size;
/
/
已有元素个数
Py_ssize_t allocated;
/
/
列表容量,可容纳个数
} PyListObject;
|
c源码来自 listobject.c 。
name_list = [ ] 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
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
/
/
缓存机制
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();
nbytes
=
size
*
sizeof(PyObject
*
);
if
(numfree) {
numfree
-
-
;
op
=
free_list[numfree];
_Py_NewReference((PyObject
*
)op);
#ifdef SHOW_ALLOC_COUNT
count_reuse
+
+
;
#endif
}
else
{
op
=
PyObject_GC_New(PyListObject, &PyList_Type);
if
(op
=
=
NULL)
return
NULL;Py
#ifdef SHOW_ALLOC_COUNT
count_alloc
+
+
;
#endif
}
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);
}
Py_SIZE(op)
=
size;
/
/
元素个数
op
-
>allocated
=
size;
/
/
容量
_PyObject_GC_TRACK(op);
/
/
放到双向链表进行维护
return
(PyObject
*
) op;
/
/
返回列表的指针
}
|
list中插入一个元素时,扩容连续的内存地址(容量),在内存创建需要插入的内容p,将地址*p放入list的空间中,所以,PyListObject的ob_item是指针的指针 。
扩容的曲线一般就是0,4,8,16,24… 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/
/
添加元素
static
int
app1(PyListObject
*
self
, PyObject
*
v)
{
/
/
获取实际元素个数
Py_ssize_t n
=
PyList_GET_SIZE(
self
);
assert
(v !
=
NULL);
if
(n
=
=
PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to list"
);
return
-
1
;
}
/
/
计算当前容量和内部元素个数
/
/
直接添加元素
/
扩容添加
if
(list_resize(
self
, n
+
1
)
=
=
-
1
)
return
-
1
;
/
/
将元素添加到ob_item,v
Py_INCREF(v);
PyList_SET_ITEM(
self
, n, v);
return
0
;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/
/
扩容机制
/
/
newsize: 已存在元素个数
+
1
static
int
list_resize(PyListObject
*
self
, Py_ssize_t newsize)
{
PyObject
*
*
items;
size_t new_allocated;
Py_ssize_t allocated
=
self
-
>allocated;
/
/
当前的容量
/
/
1
,容量大于个数
/
/
2
,个数大于容量的一半(容量足够且没有内存浪费)
if
(allocated >
=
newsize && newsize >
=
(allocated >>
1
)) {
assert
(
self
-
>ob_item !
=
NULL || newsize
=
=
0
);
Py_SIZE(
self
)
=
newsize;
return
0
;
}
/
*
*
The growth pattern
is
:
0
,
4
,
8
,
16
,
25
,
35
,
46
,
58
,
72
,
88
, ...
*
/
/
/
扩容机制的算法
new_allocated
=
(newsize >>
3
)
+
(newsize <
9
?
3
:
6
);
/
*
check
for
integer overflow
*
/
if
(new_allocated > PY_SIZE_MAX
-
newsize) {
PyErr_NoMemory();
return
-
1
;
}
else
{
new_allocated
+
=
newsize;
}
if
(newsize
=
=
0
)
new_allocated
=
0
;
/
/
扩容
/
缩容(涉及原来元素的迁移)
items
=
self
-
>ob_item;
if
(new_allocated <
=
(PY_SIZE_MAX
/
sizeof(PyObject
*
)))
PyMem_RESIZE(items, PyObject
*
, new_allocated);
else
items
=
NULL;
if
(items
=
=
NULL) {
PyErr_NoMemory();
return
-
1
;
}
/
/
赋值,更新个数和容量
self
-
>ob_item
=
items;
Py_SIZE(
self
)
=
newsize;
self
-
>allocated
=
new_allocated;
return
0
;
}
|
list.pop() 删除最后一个元素只需要修改size,不需要清除数据,下次append可以直接覆盖这个位置 指定索引位置移除后,向前补位 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
static PyObject
*
listpop(PyListObject
*
self
, PyObject
*
args)
{
Py_ssize_t i
=
-
1
;
PyObject
*
v;
int
status;
if
(!PyArg_ParseTuple(args,
"|n:pop"
, &i))
return
NULL;
if
(Py_SIZE(
self
)
=
=
0
) {
/
*
Special
-
case most common failure cause
*
/
PyErr_SetString(PyExc_IndexError,
"pop from empty list"
);
return
NULL;
}
if
(i <
0
)
i
+
=
Py_SIZE(
self
);
if
(i <
0
|| i >
=
Py_SIZE(
self
)) {
PyErr_SetString(PyExc_IndexError,
"pop index out of range"
);
return
NULL;
}
v
=
self
-
>ob_item[i];
/
/
删除最后一个,仅改变size
if
(i
=
=
Py_SIZE(
self
)
-
1
) {
status
=
list_resize(
self
, Py_SIZE(
self
)
-
1
);
assert
(status >
=
0
);
return
v;
/
*
and
v now owns the reference the
list
had
*
/
}
Py_INCREF(v);
/
/
不是最后一个,需要移动数据位置
status
=
list_ass_slice(
self
, i, i
+
1
, (PyObject
*
)NULL);
assert
(status >
=
0
);
/
*
Use status, so that
in
a release build compilers don't
*
complain about the unused name.
*
/
(void) status;
return
v;
}
|
list.clear() 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static
int
list_clear(PyListObject
*
a)
{
Py_ssize_t i;
PyObject
*
*
item
=
a
-
>ob_item;
if
(item !
=
NULL) {
i
=
Py_SIZE(a);
/
/
各个元素设置为空
Py_SIZE(a)
=
0
;
a
-
>ob_item
=
NULL;
a
-
>allocated
=
0
;
/
/
引用计数器
-
1
while
(
-
-
i >
=
0
) {
Py_XDECREF(item[i]);
}
PyMem_FREE(item);
}
return
0
;
}
|
del list 。
销毁列表对象的操作 将列表的引用计数-1 引用计数>0,还有应用的话不做操作 引用计数=0,没人使用 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
static void
list_dealloc(PyListObject
*
op)
{
Py_ssize_t i;
/
/
判断引用计数是否为
0
PyObject_GC_UnTrack(op);
Py_TRASHCAN_SAFE_BEGIN(op)
if
(op
-
>ob_item !
=
NULL) {
i
=
Py_SIZE(op);
while
(
-
-
i >
=
0
) {
Py_XDECREF(op
-
>ob_item[i]);
}
PyMem_FREE(op
-
>ob_item);
}
/
/
free_list没有
80
个的话缓存这个
list
if
(numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
free_list[numfree
+
+
]
=
op;
else
Py_TYPE(op)
-
>tp_free((PyObject
*
)op);
Py_TRASHCAN_SAFE_END(op)
}
|
就是说创建列表时,实际上不会直接开辟内存,而是先看看free_list 。
1
2
3
4
5
6
7
8
9
|
# 两次list的地址相同
>>> list1
=
[
1
,
2
,
3
]
>>>
id
(list1)
69070216L
>>>
del
list1
>>> list2
=
[
0
,
0
,
0
]
>>>
id
(list2)
69303304L
>>>
|
到此这篇关于Python源码解析之List的文章就介绍到这了,更多相关Python List内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/weixin_41884844/article/details/116796567 。
最后此篇关于Python源码解析之List的文章就讲到这里了,如果你想了解更多关于Python源码解析之List的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我想使用 R 预定义这样的列表 DATA<-list( list(list(),list(),list()), list(list(),list(),list()), list(list(),l
如何将一个列表添加到另一个列表,返回一个列表的列表? foo :: [a] -> [a] -> [[a]] 例如,我想要的结果是: foo [1,2] [3,4] 将是 [[1,2], [3,4]]。
我还没有在这里找到类似问题的解决方案,所以我会寻求你的帮助。 有 2 个列表,其中之一是列表列表: categories = ['APPLE', 'ORANGE', 'BANANA'] test_re
这个问题不同于Converting list of lists / nested lists to list of lists without nesting (这会产生一组非常具体的响应,但无法解决
原始列表转换为 List正好。为什么原始列表的列表不能转换为 List 的列表? { // works List raw = null; List wild = raw; } {
在下面的代码中,get()被调用并将其结果分配给类型为 List> 的变量. get()返回 List>并在类型参数为 T 的实例上调用设置为 ? ,所以它应该适合。 import java.util
原始列表转换为 List正好。为什么原始列表的列表不能转换为 List 的列表? { // works List raw = null; List wild = raw; } {
在insufficiently-polymorphic 作者说: def foo[A](fst: List[A], snd: List[A]): List[A] There are fewer way
我有下面的代码有效。 class ListManipulate(val list: List, val blockCount: Int) { val result: MutableList>
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
在 scala (2.9) 中转换列表列表的最佳方法是什么? 我有一个 list : List[List[A]] 我想转换成 List[A] 如何递归地实现这一点?或者还有其他更好的办法吗? 最佳答案
我编写了这个函数来确定给定元素是否存储在元组列表的列表中,但目前它只搜索第一个列表。我将如何搜索其余列表? fun findItem (name : command, ((x,y)::firstlis
我创建了一个类名 objectA,它有 4 个变量:约会时间;字符串文本;变量 1,变量 2 我需要创建一个 ObjectA() 列表。然后首先按时间对它们进行分组,其次按 var1,然后按 var2
我有一套说法 char={'J','A'} 和列表的列表 content = [[1,'J', 2], [2, 'K', 3], [2, 'A', 3], [3,'A', 9], [5, 'J', 9
我有以下列表 List >>> titles = new ArrayList >>> ();我想访问它的元素,但我不知道该怎么做.. 该列表有 1 个元素,它又包含 3 个元素,这 3 个元素中的
转换 List[List[Long]] 的最佳方法是什么?到 List[List[Int]]在斯卡拉? 例如,给定以下类型列表 List[List[Long]] val l: List[List[Lo
我有一个来自 Filereader (String) 的 List-List,如何将其转换为 List-List (Double):我必须返回一个包含 line-Array 的第一个 Values 的
我收集了List> 。我需要将其转换为List> 。这是我尝试过的, List> dataOne = GetDataOne(); var dataTwo = dataOne.Select(x => x
这个问题在这里已经有了答案: Cannot convert from List to List> (3 个答案) 关闭 7 年前。 我没有得到这段代码以任何方式编译: List a = new Ar
这个问题在这里已经有了答案: Cannot convert from List to List> (3 个答案) 关闭 7 年前。 我没有得到这段代码以任何方式编译: List a = new Ar
我是一名优秀的程序员,十分优秀!