Python中对切片赋值的原理是什么
Python中对切片赋值的原理是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
有这么个问题::
t=[1,2,3]t[1:1]=[7]printt#输出[1,7,2,3]
谁会对列表这么进行赋值呢?但是对于这个输出结果的原因确实值得去再了解下,今天看看Python的源码,了解下原理是什么。
注:本地下载的是Python2.7.6的代码,直接看这个。
在Objects/listobject.c中有一个 PyList_SetSlice 函数,是这么写的::
intPyList_SetSlice(PyObject*a,Py_ssize_tilow,Py_ssize_tihigh,PyObject*v){if(!PyList_Check(a)){PyErr_BadInternalCall();return-1;}returnlist_ass_slice((PyListObject*)a,ilow,ihigh,v);}
有用的一句就是 list_ass_slice ,那么再来看看这个函数的代码::
staticintlist_ass_slice(PyListObject*a,Py_ssize_tilow,Py_ssize_tihigh,PyObject*v){/*Because[X]DECREFcanrecursivelyinvokelistoperationsonthislist,wemustpostponeall[X]DECREFactivityuntilafterthelistisbackinitscanonicalshape.Thereforewemustallocateanadditionalarray,'recycle',intowhichwetemporarilycopytheitemsthataredeletedfromthelist.:-(*/PyObject*recycle_on_stack[8];PyObject**recycle=recycle_on_stack;/*willallocatemoreifneeded*/PyObject**item;PyObject**vitem=NULL;PyObject*v_as_SF=NULL;/*PySequence_Fast(v)*/Py_ssize_tn;/*#ofelementsinreplacementlist*/Py_ssize_tnorig;/*#ofelementsinlistgettingreplaced*/Py_ssize_td;/*Changeinsize*/Py_ssize_tk;size_ts;intresult=-1;/*guiltyuntilprovedinnocent*/#defineb((PyListObject*)v)if(v==NULL)n=0;else{if(a==b){/*Specialcase"a[i:j]=a"--copybfirst*/v=list_slice(b,0,Py_SIZE(b));if(v==NULL)returnresult;result=list_ass_slice(a,ilow,ihigh,v);Py_DECREF(v);returnresult;}v_as_SF=PySequence_Fast(v,"canonlyassignaniterable");if(v_as_SF==NULL)gotoError;/*要赋值的长度n*/n=PySequence_Fast_GET_SIZE(v_as_SF);vitem=PySequence_Fast_ITEMS(v_as_SF);}if(ilow<0)ilow=0;elseif(ilow>Py_SIZE(a))ilow=Py_SIZE(a);if(ihigh<ilow)ihigh=ilow;elseif(ihigh>Py_SIZE(a))ihigh=Py_SIZE(a);norig=ihigh-ilow;assert(norig>=0);d=n-norig;if(Py_SIZE(a)+d==0){Py_XDECREF(v_as_SF);returnlist_clear(a);}item=a->ob_item;/*recycletheitemsthatweareabouttoremove*/s=norig*sizeof(PyObject*);if(s>sizeof(recycle_on_stack)){recycle=(PyObject**)PyMem_MALLOC(s);if(recycle==NULL){PyErr_NoMemory();gotoError;}}memcpy(recycle,&item[ilow],s);if(d<0){/*Delete-ditems*/memmove(&item[ihigh+d],&item[ihigh],(Py_SIZE(a)-ihigh)*sizeof(PyObject*));list_resize(a,Py_SIZE(a)+d);item=a->ob_item;}elseif(d>0){/*Insertditems*/k=Py_SIZE(a);if(list_resize(a,k+d)<0)gotoError;item=a->ob_item;printf("关键点\n");/*把list对应切片后一位的值之后的所有内容向后移动所赋值的大小按照上面的python代码这里就是原理的t:|1|2|3|后移一位,因为len([7])=1|1|空|2|3|把后两个移位*/memmove(&item[ihigh+d],&item[ihigh],(k-ihigh)*sizeof(PyObject*));}/*赋值操作,即把[7]赋值到t里的对应位置上ilow是1,n是1*/for(k=0;k<n;k++,ilow++){PyObject*w=vitem[k];Py_XINCREF(w);item[ilow]=w;}for(k=norig-1;k>=0;--k)Py_XDECREF(recycle[k]);result=0;Error:if(recycle!=recycle_on_stack)PyMem_FREE(recycle);Py_XDECREF(v_as_SF);returnresult;#undefb}
源码内有详细注释,编程问题的研究最好的解释还是源码。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。