當前位置:
首頁 > 知識 > Python 源码阅读:list

Python 源码阅读:list

新媒体管家


点击上方“

Python开发

”,选择“置顶公众号”


关键时刻,第一时间送达!






源码位置 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

(

op

)


}








对一个列表对象

PyListObject

,

回收时

,

ob

_

item会被回收

,

其每个元素指向的对象引用

-

1.


但是

PyListObject

对象本身

,

如果缓冲池未满

,

会被放入缓冲池

,

复用




缓冲池结构





List的操作过程




插入





1.

resize

n

+

1


2.

确定插入点


3.

插入点后所有元素后移


4.

执行插入




示例





>>>

a

=

[

1

,

2

,

3

]


>>>

a

.

insert

(

0

,

9

)


>>>

a


[

9

,

1

,

2

,

3

]




append





1.

resize

n

+

1


2.

放入最后一个位置

(

ob_size

)




示例





>>>

a

=

[

1

,

2

,

3

]


>>>

a

.

append

(

4

)


>>>

a


[

1

,

2

,

3

,

4

]




extend





1.

计算两个

list

大小

m

n


2.

resize

m

+

n

(

此时本身被复制

)


3.

遍历长度为

n

的数组

,

ob_item

+

m

的位置开始加入




示例





>>>

m

=

[

1

,

2

,

3

]


>>>

n

=

[

4

,

5

]


>>>

m

.

extend

(

n

)


>>>

m


[

1

,

2

,

3

,

4

,

5

]




删除





1.

找到要删除元素位置


2.

删除之

,

后面元素前移




示例





>>>

a

=

[

1

,

2

,

3

,

2

]


>>>

a

.

remove

(

2

)


>>>

a


[

1

,

3

,

2

]





  • 来源:

    伯乐在线 - wklken



  • Python开发整理发布,转载请

    联系作者获得授权




【点击成为安卓大神】

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python开发 的精彩文章:

python源码阅读笔记之GC
Python 中的属性访问与描述符
Python 源码阅读:类型
Python 面向对象(进阶篇)
让你的 Python 代码优雅又地道

TAG:Python开发 |