python同步赋值原理_Python中对切片赋值原理分析

有这么个问题::t = [1, 2, 3]

t[1:1] = [7]

print t  # 输出 [1, 7, 2, 3]

谁会对列表这么进行赋值呢?但是对于这个输出结果的原因确实值得去再了解下,今天看看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;

}

return list_ass_slice((PyListObject *)a, ilow, ihigh, v);

}

有用的一句就是 list_ass_slice ,那么再来看看这个函数的代码::static int

list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)

{

#zs# Because [X]DECREF can recursively invoke list operations on

this list, we must postpone all [X]DECREF activity until

after the list is back in its canonical shape.  Therefore

we must allocate an additional array, 'recycle', into which

we temporarily copy the items that are deleted from the

list. :-( #fzs#

PyObject *recycle_on_stack[8];

PyObject **recycle = recycle_on_stack; #zs# will allocate more if needed #fzs#

PyObject **item;

PyObject **vitem = NULL;

PyObject *v_as_SF = NULL; #zs# PySequence_Fast(v) #fzs#

Py_ssize_t n; #zs# # of elements in replacement list #fzs#

Py_ssize_t norig; #zs# # of elements in list getting replaced #fzs#

Py_ssize_t d; #zs# Change in size #fzs#

Py_ssize_t k;

size_t s;

int result = -1;            #zs# guilty until proved innocent #fzs#

#define b ((PyListObject *)v)

if (v == NULL)

n = 0;

else {

if (a == b) {

#zs# Special case "a[i:j] = a" -- copy b first #fzs#

v = list_slice(b, 0, Py_SIZE(b));

if (v == NULL)

return result;

result = list_ass_slice(a, ilow, ihigh, v);

Py_DECREF(v);

return result;

}

v_as_SF = PySequence_Fast(v, "can only assign an iterable");

if(v_as_SF == NULL)

goto Error;

#zs#

要赋值的长度n

#fzs#

n = PySequence_Fast_GET_SIZE(v_as_SF);

vitem = PySequence_Fast_ITEMS(v_as_SF);

}

if (ilow 

ilow = 0;

else if (ilow > Py_SIZE(a))

ilow = Py_SIZE(a);

if (ihigh 

ihigh = ilow;

else if (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);

return list_clear(a);

}

item = a->ob_item;

#zs# recycle the items that we are about to remove #fzs#

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 

memmove(&item[ihigh d], &item[ihigh],

(Py_SIZE(a) - ihigh)*sizeof(PyObject *));

list_resize(a, Py_SIZE(a)   d);

item = a->ob_item;

}

else if (d > 0) { #zs# Insert d items #fzs#

k = Py_SIZE(a);

if (list_resize(a, k d) 

goto Error;

item = a->ob_item;

printf("关键点n");

#zs#

把list对应切片后一位的值之后的所有内容向后移动所赋值的大小

按照上面的python代码这里就是

原理的t:

|1|2|3|

后移一位,因为len([7]) = 1

|1|空|2|3|把后两个移位

#fzs#

memmove(&item[ihigh d], &item[ihigh],

(k - ihigh)*sizeof(PyObject *));

}

#zs#

赋值操作,即把[7]赋值到t里的对应位置上

ilow是1, n是1

#fzs#

for (k = 0; k 

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);

return result;

#undef b

}

源码内有详细注释,编程问题的研究最好的解释还是源码。

您可能感兴趣的文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值