欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過(guò)源碼分析Python中的切片賦值

 更新時(shí)間:2017年05月08日 09:03:04   作者:the5fire  
因?yàn)榻?jīng)常取指定索引范圍的操作,用循環(huán)十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡(jiǎn)化這種操作。而下面這篇文章則通過(guò)源碼給大家分析介紹了Python中切片賦值的相關(guān)資料,需要的朋友可以參考學(xué)習(xí),下面來(lái)一起看看吧。

本文主要介紹的關(guān)于Python切片賦值的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面來(lái)一起看看詳細(xì)的介紹:

昨天有同學(xué)問(wèn)了我這么個(gè)問(wèn)題:

t = [1, 2, 3]
t[1:1] = [7] # 感謝@一往直前 的疑問(wèn),之前寫(xiě)為 t[1:1] = 7了
print t # 輸出 [1, 7, 2, 3]

這個(gè)問(wèn)題之前還真沒(méi)遇到過(guò),有誰(shuí)會(huì)對(duì)列表這么進(jìn)行賦值嗎?不過(guò)對(duì)于這個(gè)輸出結(jié)果的原因確實(shí)值得去再了解下,畢竟之前也看過(guò)《Python源碼分析》。(題外話(huà):據(jù)說(shuō)最近有大牛在寫(xiě)新的版本)

想著今天有空看看Python的源碼,去了解下原理是什么。

注:我本地之前下載的是Python2.7.6的代碼,直接看的這個(gè)。

在Objects/listobject.c中有一個(gè) PyList_SetSlice 函數(shù),是這么寫(xiě)的:

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 ,那么再來(lái)看看這個(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;
  /*
  the5fire注:
  要賦值的長(zhǎng)度n
  */
  n = PySequence_Fast_GET_SIZE(v_as_SF);
  vitem = PySequence_Fast_ITEMS(v_as_SF);
 }
 if (ilow < 0)
  ilow = 0;
 else if (ilow > Py_SIZE(a))
  ilow = Py_SIZE(a);

 if (ihigh < ilow)
  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 < 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;
 }
 else if (d > 0) { /* Insert d items */
  k = Py_SIZE(a);
  if (list_resize(a, k+d) < 0)
   goto Error;
  item = a->ob_item;
  printf("關(guān)鍵點(diǎn)\n");
  /*
  the5fire注:
  把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 *));
 }
 /*
 the5fire注:
 賦值操作,即把[7]賦值到t里的對(duì)應(yīng)位置上
 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);
 return result;
#undef b
}

看了知乎,stackoverflow上的解答,發(fā)現(xiàn)源碼還是最好的解釋。上述關(guān)鍵位置已經(jīng)加了注釋?zhuān)瑧?yīng)該很好理解。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 基于Pycharm加載多個(gè)項(xiàng)目過(guò)程圖解

    基于Pycharm加載多個(gè)項(xiàng)目過(guò)程圖解

    這篇文章主要介紹了基于Pycharm加載多個(gè)項(xiàng)目過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 使用 django orm 寫(xiě) exists 條件過(guò)濾實(shí)例

    使用 django orm 寫(xiě) exists 條件過(guò)濾實(shí)例

    這篇文章主要介紹了使用 django orm 寫(xiě) exists 條件過(guò)濾實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • Python?列表(list)的常用方法

    Python?列表(list)的常用方法

    這篇文章主要介紹了Python?列表(list)的常用方法,這節(jié)主要講列表,列表用于存儲(chǔ)任意數(shù)目、任意類(lèi)型的數(shù)據(jù)集合,本文通過(guò)示例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2023-05-05
  • Python中@符號(hào)的具體使用

    Python中@符號(hào)的具體使用

    本文主要介紹了Python中@符號(hào)的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 分享11個(gè)Python自動(dòng)化操作Excel的方法

    分享11個(gè)Python自動(dòng)化操作Excel的方法

    這篇文章主要給大家分享的是11個(gè)Python自動(dòng)化操作Excel的方法,自動(dòng)化辦公,我相信很多人都有強(qiáng)烈的需求,今天我教大家如何利用Python自動(dòng)化操作Excel,需要的朋友可以參考一下
    2022-02-02
  • 基于Python實(shí)現(xiàn)批量保存視頻到本地

    基于Python實(shí)現(xiàn)批量保存視頻到本地

    我們刷視頻時(shí)常常會(huì)想把精彩的視頻保存到本地,如果少數(shù)的還行,如果有很多的話(huà)一個(gè)個(gè)保存太麻煩了。本文教你如何用Python實(shí)現(xiàn)視頻批量保存到本地,需要的可以參考一下
    2022-05-05
  • python三引號(hào)如何輸入

    python三引號(hào)如何輸入

    在本篇文章里小編給大家整理的是關(guān)于python三引號(hào)輸入方法及相關(guān)實(shí)例,需要的朋友們可以學(xué)習(xí)下。
    2020-07-07
  • Python數(shù)據(jù)類(lèi)型探索列表魔法世界

    Python數(shù)據(jù)類(lèi)型探索列表魔法世界

    這篇文章主要為大家介紹了Python數(shù)據(jù)類(lèi)型探索列表魔法世界,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 通過(guò)PHP與Python代碼對(duì)比的語(yǔ)法差異詳解

    通過(guò)PHP與Python代碼對(duì)比的語(yǔ)法差異詳解

    這篇文章主要介紹了通過(guò)PHP與Python代碼對(duì)比淺析語(yǔ)法差異,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • python?Prophet時(shí)間序列預(yù)測(cè)工具庫(kù)使用功能探索

    python?Prophet時(shí)間序列預(yù)測(cè)工具庫(kù)使用功能探索

    Python?Prophet是一個(gè)強(qiáng)大的時(shí)間序列預(yù)測(cè)工具,由Facebook開(kāi)發(fā),具有易用性和高度可定制性的特點(diǎn),本文將深入介紹Python?Prophet的基本概念、安裝方法以及如何使用它進(jìn)行時(shí)間序列預(yù)測(cè),并提供豐富的示例代碼來(lái)幫助大家入門(mén)
    2024-01-01

最新評(píng)論