最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

通過源碼分析Python中的切片賦值

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

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

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

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

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

想著今天有空看看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;
  /*
  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)加了注釋,應(yīng)該很好理解。

總結(jié)

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

相關(guān)文章

  • python使用numpy實(shí)現(xiàn)直方圖反向投影示例

    python使用numpy實(shí)現(xiàn)直方圖反向投影示例

    今天小編就為大家分享一篇python使用numpy實(shí)現(xiàn)直方圖反向投影示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-01-01
  • 查找python項(xiàng)目依賴并生成requirements.txt的方法

    查找python項(xiàng)目依賴并生成requirements.txt的方法

    今天小編就為大家分享一篇查找python項(xiàng)目依賴并生成requirements.txt的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • django 認(rèn)證類配置實(shí)現(xiàn)

    django 認(rèn)證類配置實(shí)現(xiàn)

    本文主要介紹了django 認(rèn)證類配置實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Python 實(shí)現(xiàn)RSA加解密文本文件

    Python 實(shí)現(xiàn)RSA加解密文本文件

    這篇文章主要介紹了Python 實(shí)現(xiàn)RSA加解密文本文件的方法,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-12-12
  • 使用Python3 poplib模塊刪除服務(wù)器多天前的郵件實(shí)現(xiàn)代碼

    使用Python3 poplib模塊刪除服務(wù)器多天前的郵件實(shí)現(xiàn)代碼

    這篇文章主要介紹了使用Python3 poplib模塊刪除多天前的郵件的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置的教程詳解

    Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置的教程詳解

    這篇文章主要介紹了Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Python對(duì)PDF文件的常用操作方法詳解

    Python對(duì)PDF文件的常用操作方法詳解

    PDF是Portable?Document?Format的縮寫,這類文件通常使用`.pdf`作為其擴(kuò)展名。在日常開發(fā)工作中,最容易遇到的就是從PDF中讀取文本內(nèi)容以及用已有的內(nèi)容生成PDF文檔這兩個(gè)任務(wù)。本文為大家介紹了幾個(gè)Python中常見的PDF操作,需要的可以參考一下
    2022-05-05
  • Python判斷文件和字符串編碼類型的實(shí)例

    Python判斷文件和字符串編碼類型的實(shí)例

    下面小編就為大家分享一篇Python判斷文件和字符串編碼類型的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • python?GUI多行輸入文本Text的實(shí)現(xiàn)

    python?GUI多行輸入文本Text的實(shí)現(xiàn)

    這篇文章主要介紹了python?GUI多行輸入文本Text的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • python?pandas?query的使用方法

    python?pandas?query的使用方法

    這篇文章主要介紹了python?pandas?query的使用方法,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-09-09

最新評(píng)論

卢龙县| 宾阳县| 获嘉县| 稷山县| 永顺县| 龙州县| 多伦县| 淮安市| 卓尼县| 安远县| 虞城县| 彭泽县| 枣庄市| 长岭县| 隆尧县| 乌什县| 贵州省| 香港| 宝应县| 扶余县| 朝阳区| 平湖市| 成安县| 杂多县| 兴隆县| 承德市| 甘德县| 扶沟县| 东丰县| 蓝田县| 万山特区| 叙永县| 磐石市| 长武县| 民勤县| 祁东县| 嵊州市| 小金县| 诸城市| 疏附县| 舟山市|