1.python列表的深/浅拷贝Python有一个常用的数据类型:list。在使用list的时候,往往需要考虑一件事,那就是:浅拷贝和深拷贝。至于什么是深拷贝和浅拷贝,先从一个示例代码来分析:importcopy#listsourcedatausedinthetestlists=[[1,2,3],4,5,6]deflow_copy():#list浅拷贝low_list=copy.copy(lists)returnlist(low_list)defdeep_copy():#list深拷贝deep_list=copy.deepcopy(lists)returnlist(deep_list)if__name__=="__main__":print("sourcelist:",lists)#分别获取浅拷贝、深拷贝列表对象=====================")#将值7追加到源数据的第0条数据print("将值7追加到源数据的第0条数据list,start")lists[0].append(7)print("将值7附加到源列表的第0条数据,end")print("===========================")#源数据的第0条数据加值7后校验,深拷贝数据的变化print("sourcelist:",lists)print("浅拷贝列表:",lists_c)print("深拷贝列表:",lists_d)#执行结果##源列表:[[1,2,3],4,5,6]#浅拷贝列表:[[1,2,3],4,5,6]#深拷贝列表:[[1,2,3],4,5,6]#==========================#对于源列表的第0个给数据加一个值7,start#给source列表的第0条数据加一个值7,end#===================================#sourcelist:[[1,2,3,7],4,5,6]#shallowcopylist:[[1,2,3,7],4,5,6]#深拷贝列表:[[1,2,3],4,5,6]从示例代码可以看出:经过list的浅拷贝和深拷贝后,修改源数据会直接影响到浅拷贝的数据,而深拷贝的数据将直接受到影响。复制的数据不受影响这说明了什么,又是如何实现的?2、pyhtonlist的实现首先要说明几点:python的底层源码是用C语言实现的。都是对象)Python对象大致可以分为以下几种:参考https://flaggo.github.io/python3-source-code-analysis/objects/object/Fundamentalobject:TypeobjectNumericobject:NumericobjectSequenceobject:容纳其他对象的序列集合对象Mappingobject:类似于C++中map的关联对象Internalobject:Python虚拟机在运行时内部使用的对象3.listobject在python源码实现中,list的结构如下:/源文件:include/listobject.h//listobject.htypedefstruct{//对象的公共头PyObject_VAR_HEAD//指向列表元素的指针向量,list[0]为ob_item[0]//可以看到ob_item是一个secondaryPointer//也就是说,**ob_item表示它是一个指向PyObject类型指针数组的指针//*ob_item表示它是一个PyObject类型指针数组/*Vectorofpointerstolistelements.list[0]isob_item[0],etc.*/PyObject**ob_item;/*ob_itemcontainsspacefor'allocated'elements.Thenumber*currentlyinuseisob_size.*Invariants:*0<=ob_size<=allocated*len(list)==ob_size*ob_item==NULLimpliesob_size==allocated==0*list.sort()临时设置allocated为-1到检测突变。**项目通常不能为NULL,除非在构造期间*thelistisnotyetvisibleoutsidethefunctionthatbuildsit.*///列表包含元素的总数Py_ssize_tallocated;}PyListObject;从list的结构可以看出ob_item字段实际存放的是object,是指向指针数组的指针,所以我们知道PyListObject结构体是一个多级结构体创建列表的过程主要分为两步:创建一个PyListObject结构体并初始化ob_item指向的指针数组//源文件位置:Objects/listobject.c//新建一个listPyObject*PyList_New(Py_ssize_tsize){//判断列表的大小是否合法if(size<0){PyErr_BadInternalCall();returnNULL;}struct_Py_list_state*state=get_list_state();//最终创建的列表对象指针PyListObject*op;#ifdefPy_DEBUG//PyList_New()mustnotbecalledafter_PyList_Fini()assert(state->numfree!=-1);#endifif(state->numfree){state->numfree--;op=state->free_list[state->numfree];_Py_NewReference((PyObject*)op);}else{//新建一个listop=PyObject_GC_New(PyListObject,&PyList_Type);if(op==NULL){returnNULL;}}if(size<=0){op->ob_item=NULL;}else{op->ob_item=(PyObject**)PyMem_Calloc(size,sizeof(PyObject*));if(op->ob_item==NULL){Py_DECREF(op);returnPyErr_NoMemory();}}Py_SET_SIZE(op,size);op->allocated=size;_PyObject_GC_TRACK(op);return(PyObject*)op;}4.listshallowcopy//源文件位置:Objects/listobject.c/*[clinicinput]list.copyReturnashallowcopyofthelist.[clinicstartgeneratedcode]*///列表的浅拷贝ihighPy_ssize_t的类型是当前系统中一个指针的大小;if(len<=0){returnPyList_New(0);}//生成一个新的listnp=(PyListObject*)list_new_prealloc(len);if(np==NULL)returnNULL;//从list的第一个位置开始a->ob_itemmoveilow,即:移动到第ilow个数值元素的指针位置src=a->ob_item+ilow;//新列表数值列表的第一个位置dest=np->ob_item;//copy,注意:只是复制了对象的指针for(i=0;i
