最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
通过源码怎么去分析Python中的切片赋值
时间:2017-05-09 编辑:简简单单 来源:一聚教程网
本文主要介绍的关于Python切片赋值的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:
昨天有同学问了我这么个问题:
代码如下 | 复制代码 |
t=[1,2,3] t[1:1]=[7]# 感谢@一往直前 的疑问,之前写为 t[1:1] = 7了 printt# 输出 [1, 7, 2, 3] |
这个问题之前还真没遇到过,有谁会对列表这么进行赋值吗?不过对于这个输出结果的原因确实值得去再了解下,毕竟之前也看过《Python源码分析》。(题外话:据说最近有大牛在写新的版本)
想着今天有空看看Python的源码,去了解下原理是什么。
注:我本地之前下载的是Python2.7.6的代码,直接看的这个。
在Objects/listobject.c中有一个 PyList_SetSlice 函数,是这么写的:
代码如下 | 复制代码 |
int PyList_SetSlice(PyObject*a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject*v) { if(!PyList_Check(a)) { PyErr_BadInternalCall(); return-1; } returnlist_ass_slice((PyListObject*)a, ilow, ihigh, v); } |
有用的一句就是 list_ass_slice ,那么再来看看这个函数的代码:
代码如下 | 复制代码 |
staticint list_ass_slice(PyListObject*a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject*v) { /*Because [X]DECREF can recursively invokelistoperations on thislist, we must postponeall[X]DECREF activity until after thelistisbackinits canonical shape. Therefore we must allocate an additional array,'recycle', into which we temporarily copy the items that are deletedfromthe list. :-(*/ PyObject*recycle_on_stack[8]; PyObject**recycle=recycle_on_stack;/*will allocate moreifneeded*/ PyObject**item; PyObject**vitem=NULL; PyObject*v_as_SF=NULL;/*PySequence_Fast(v)*/ Py_ssize_t n;/*# of elements in replacement list */ Py_ssize_t norig;/*# of elements in list getting replaced */ Py_ssize_t d;/*Changeinsize*/ Py_ssize_t k; size_t s; intresult=-1; /*guilty until proved innocent*/ #define b ((PyListObject *)v) if(v==NULL) n=0; else{ if(a==b) { /*Special case"a[i:j] = a"--copy b first*/ 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,"can only assign an iterable"); if(v_as_SF==NULL) goto Error; /* the5fire注: 要赋值的长度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; /*recycle the items that we are about to remove*/ s=norig*sizeof(PyObject*); if(s > sizeof(recycle_on_stack)) { recycle=(PyObject**)PyMem_MALLOC(s); if(recycle==NULL) { PyErr_NoMemory(); goto Error; } } memcpy(recycle, &item[ilow], s);
if(d<0) {/*Delete-d items*/ 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) {/*Insert d items*/ k=Py_SIZE(a); if(list_resize(a, k+d)<0) goto Error; item=a->ob_item; printf("关键点\n"); /* the5fire注: 把list对应切片后一位的值之后的所有内容向后移动所赋值的大小 按照上面的python代码这里就是 原理的t: |1|2|3| 后移一位,因为len([7])=1 |1|空|2|3|把后两个移位 */ memmove(&item[ihigh+d], &item[ihigh], (k-ihigh)*sizeof(PyObject*)); } /* the5fire注: 赋值操作,即把[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; #undef b } |
看了知乎,stackoverflow上的解答,发现源码还是最好的解释。上述关键位置已经加了注释,应该很好理解
相关文章
- 阴阳师神龛金御札兑换随机SSR 阴阳师金御札值不值得换 07-31
- 微软新版Surface Laptop预售 你会充值信仰吗 07-31
- 火影忍者手游泳装雏田好吗 值得买吗 07-10
- 一加5对比努比亚Z17 谁是高颜值超长续航战斗机 07-06
- 英雄无敌罗伊德技能实力分析 罗伊德值得培养吗 07-06
- WPS表格添加筛选唯一值功能教程 07-04