python列表切片赋值_Python中对切片赋值原理分析
有這么個(gè)問題::t?=?[1,?2,?3]
t[1:1]?=?[7]
print?t??#?輸出?[1,?7,?2,?3]
誰會(huì)對(duì)列表這么進(jìn)行賦值呢?但是對(duì)于這個(gè)輸出結(jié)果的原因確實(shí)值得去再了解下,今天看看Python的源碼,了解下原理是什么。
注:本地下載的是Python2.7.6的代碼,直接看這個(gè)。
在Objects/listobject.c中有一個(gè) PyList_SetSlice 函數(shù),是這么寫的::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 ,那么再來看看這個(gè)函數(shù)的代碼::static?int
list_ass_slice(PyListObject?*a,?Py_ssize_t?ilow,?Py_ssize_t?ihigh,?PyObject?*v)
{
/*?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.?:-(?*/
PyObject?*recycle_on_stack[8];
PyObject?**recycle?=?recycle_on_stack;?/*?will?allocate?more?if?needed?*/
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;?/*?Change?in?size?*/
Py_ssize_t?k;
size_t?s;
int?result?=?-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)
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;
/*
要賦值的長(zhǎng)度n
*/
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;
/*?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?
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)?{?/*?Insert?d?items?*/
k?=?Py_SIZE(a);
if?(list_resize(a,?k d)?
goto?Error;
item?=?a->ob_item;
printf("關(guān)鍵點(diǎn)\n");
/*
把list對(duì)應(yīng)切片后一位的值之后的所有內(nèi)容向后移動(dòng)所賦值的大小
按照上面的python代碼這里就是
原理的t:
|1|2|3|
后移一位,因?yàn)閘en([7])?=?1
|1|空|2|3|把后兩個(gè)移位
*/
memmove(&item[ihigh d],?&item[ihigh],
(k?-?ihigh)*sizeof(PyObject?*));
}
/*
賦值操作,即把[7]賦值到t里的對(duì)應(yīng)位置上
ilow是1,?n是1
*/
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
}
源碼內(nèi)有詳細(xì)注釋,編程問題的研究最好的解釋還是源碼。
總結(jié)
以上是生活随笔為你收集整理的python列表切片赋值_Python中对切片赋值原理分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php date 有warning,PH
- 下一篇: phalanger php compil