Python Notes:range

range对象支持无穷大数迭代

//object
typedef struct {
    PyObject_HEAD
    PyObject *start;
    PyObject *stop;
    PyObject *step;
    PyObject *length;
} rangeobject;

新建一个range对象

static PyObject *
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
    return range_from_array(
        type, _PyTuple_ITEMS(args),     //获取参数对象
        PyTuple_GET_SIZE(args)    //获取参数个数
    );
}

static PyObject *
range_from_array(
    PyTypeObject *type, //对象
    PyObject *const *args, //参数指针
    Py_ssize_t num_args    //参数个数
)
{
    rangeobject *obj;
    PyObject *start = NULL, *stop = NULL, *step = NULL;

    switch (num_args) {
        case 3:    //像range(1,10,2)的情况
            step = args[2];    //取步长
        case 2:    //像range(1,10)的情况
            start = PyNumber_Index(args[0]);
            if (!start) {
                return NULL;
            }
            stop = PyNumber_Index(args[1]);
            if (!stop) {
                return NULL;
            }
            step = PyLong_FromLong(1);  //步长自动赋1
            if (!step) {
                return NULL;
            }
            break;
        case 1:    //像range(10)的情况
            stop = PyNumber_Index(args[0]);
            if (!stop) {
                return NULL;
            }
            start = _PyLong_Zero;    //起始位置自动赋0
            step = _PyLong_One;    //步长自动赋1
            break;
        case 0:    //错误
            PyExc_TypeError
                            
            return NULL;
        default:    //错误
            PyExc_TypeError,
                         
            return NULL;
    }
    obj = make_range_object(type, start, stop, step);//创建对象
    if (obj != NULL) {
        return (PyObject *) obj;
    }

    return NULL;
}

//构建range对象
static rangeobject *
make_range_object(PyTypeObject *type, PyObject *start,
                  PyObject *stop, PyObject *step)
{
    rangeobject *obj = NULL;
    PyObject *length;
    length = compute_range_length(start, stop, step);    //计算迭代次数
    if (length == NULL) {
        return NULL;
    }
    obj = PyObject_New(rangeobject, type);    //分配内存
    
    //设置属性
    obj->start = start;
    obj->stop = stop;
    obj->step = step;
    obj->length = length;
    return obj;
}

//计算range对象迭代次数
static PyObject*
compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
{

    int cmp_result;
    PyObject *lo, *hi;
    PyObject *diff = NULL;
    PyObject *tmp1 = NULL, *tmp2 = NULL, *result;
    
    //step是否大于0
    cmp_result = PyObject_RichCompareBool(step, _PyLong_Zero, Py_GT);
    //比较错误
    if (cmp_result == -1)
        return NULL;    //返回NULL代表错误
    //大于0
    if (cmp_result == 1) {
        lo = start;
        hi = stop;
    //小于0,起始位置和结束位置对调,步长转成正数
    } else {
        lo = stop;    
        hi = start;
        step = PyNumber_Negative(step);
        if (!step)
            return NULL;
    }
    
    //起始位置大于结束位置
    cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
    if (cmp_result != 0) {
        if (cmp_result < 0)
            return NULL;
        return PyLong_FromLong(0);//返回0
    }
    
    //tmp = hi - lo
    if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL)
        goto Fail;
    
    //diif = tmp1 - 1    不减一可能会超过范围,造成非法访问
    if ((diff = PyNumber_Subtract(tmp1, _PyLong_One)) == NULL)
        goto Fail;
    
    //tmp2 = diff / step    向下取整除
    if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL)
        goto Fail;
    
    //result = tmp2 + 1    向上取整
    if ((result = PyNumber_Add(tmp2, _PyLong_One)) == NULL)
        goto Fail;

    return result;

  Fail:
    return NULL;
}

转换为可迭代的range对象

typedef struct {
        PyObject_HEAD
        long    index;
        long    start;
        long    step;
        long    len;
} rangeiterobject;        
//long类型的迭代器对象,32位系统中long是4个字节;64位系统中long 是8个字节

typedef struct {
    PyObject_HEAD
    PyObject *index;
    PyObject *start;
    PyObject *step;
    PyObject *len;
} longrangeiterobject;    //长整形的range迭代器对象,支持无穷大迭代
//因为range的迭代时一个时间复杂度高的操作,所以python对此进行了优化

static PyObject *
range_iter(PyObject *seq)
{
    rangeobject *r = (rangeobject *)seq;
    longrangeiterobject *it;
    long lstart, lstop, lstep;
    PyObject *int_it;

    lstart = PyLong_AsLong(r->start);    //尝试转换为long整形8字节
    if (lstart == -1 && PyErr_Occurred()) {
        goto long_range;
    }
    lstop = PyLong_AsLong(r->stop);    //尝试转换为long整形8字节
    if (lstop == -1 && PyErr_Occurred()) {
        goto long_range;
    }
    lstep = PyLong_AsLong(r->step);    //尝试转换为long整形8字节
    if (lstep == -1 && PyErr_Occurred()) {
        goto long_range;
    }
    //创建rangeiterobject,也就是long整形对象,时间和空间效率相对较好
    int_it = fast_range_iter(lstart, lstop, lstep);
    if (int_it == NULL && PyErr_ExceptionMatches(PyExc_OverflowError)) {
        goto long_range;
    }
    return (PyObject *)int_it;

  long_range:
    //创建longrangeiterobject,python通用数字类型,支持无穷大,但时间和空间效率都较差
    it = PyObject_New(longrangeiterobject, &PyLongRangeIter_Type);
    
    //设置属性
    it->start = r->start;    //起始位置
    it->step = r->step;    //步长
    it->len = r->length;    //长度
    it->index = _PyLong_Zero;    //索引

    return (PyObject *)it;
}

迭代rangeiterobject对象

static PyObject *
rangeiter_next(rangeiterobject *r)
{    
    //比较迭代次数
    if (r->index < r->len)
        //返回对应数:起始位置+索引*步长,索引=索引 + 1
        return PyLong_FromLong((long)(r->start +
                                      (unsigned long)(r->index++) * r->step));
    //结束
    return NULL;
}

迭代longrangeiter对象

//实际上和上面的操作一样,只是调用了对象方法,以支持无穷大数计算
static PyObject *
longrangeiter_next(longrangeiterobject *r)
{
    PyObject *product, *new_index, *result;
    if (PyObject_RichCompareBool(r->index, r->len, Py_LT) != 1)
        return NULL;

    new_index = PyNumber_Add(r->index, _PyLong_One);
    if (!new_index)
        return NULL;

    product = PyNumber_Multiply(r->index, r->step);
    if (!product) {
        Py_DECREF(new_index);
        return NULL;
    }

    result = PyNumber_Add(r->start, product);
    Py_DECREF(product);
    if (result) {
        Py_SETREF(r->index, new_index);
    }
    else {
        Py_DECREF(new_index);
    }

    return result;
}

 

你可能感兴趣的:(Python)