zoukankan      html  css  js  c++  java
  • 关于Python 中切片的问题

    偶然发现一个有趣的问题:

    list = ['a','b','c','d','e']
    print(list[10:])                                                                                                              ·      

    大家猜猜这个打印结果是什么,事实上打印的是[] 空列表,并不会出现IndexError的问题,那么如果是 print(list[10])呢,这时就会出现index error的问题,这是为什么呢?

    笔者查看了下Python的源码,切片调用的是PyList_GetSlice方法,获取元素调用的是 PyList_GetItem 方法,源码如下:

    PyObject *
    PyList_GetItem(PyObject *op, Py_ssize_t i)
    {
        if (!PyList_Check(op)) {
            PyErr_BadInternalCall();
            return NULL;
        }
      //超出索引范围会报错
    if (i < 0 || i >= Py_SIZE(op)) { if (indexerr == NULL) { indexerr = PyUnicode_FromString( "list index out of range"); if (indexerr == NULL) return NULL; } PyErr_SetObject(PyExc_IndexError, indexerr); return NULL; } return ((PyListObject *)op) -> ob_item[i]; }

    可以得知当索引为10时,超出了list size 故而引发index 异常,然而切片代码如下:

    static PyObject *
    list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
    {
        PyListObject *np;
        PyObject **src, **dest;
        Py_ssize_t i, len;
        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);
        len = ihigh - ilow;
        np = (PyListObject *) PyList_New(len);
        if (np == NULL)
            return NULL;
    
        src = a->ob_item + ilow;
        dest = np->ob_item;
        for (i = 0; i < len; i++) {
            PyObject *v = src[i];
            Py_INCREF(v);
            dest[i] = v;
        }
        return (PyObject *)np;
    }
    
    PyObject *
    PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
    {
        if (!PyList_Check(a)) {
            PyErr_BadInternalCall();
            return NULL;
        }
        return list_slice((PyListObject *)a, ilow, ihigh);
    }

    可以看出即使切片的两个值大于元素个数也不会引发异常。

  • 相关阅读:
    《Redis内存数据库》Redis主复制集(主从复制)
    《Redis内存数据库》Redis消息模式
    《Redis内存数据库》redis配置文件说明
    《Redis内存数据库》Redis事务
    《Redis内存数据库》Redis持久化实现方式和原理
    《Redis内存数据库》Redis基本操作命令
    《Redis内存数据库》Redis权限管理
    yum install 与 yum groupinstall 的区别
    LNMP卸载
    Vim配置 终端背景色配置
  • 原文地址:https://www.cnblogs.com/mlmy/p/13266902.html
Copyright © 2011-2022 走看看