mas*_*pao 5 python indexing python-3.x python-internals
由于range对象按需生成值,是否意味着无论何时索引范围,迭代协议都会被调用到该索引?
我的意思是:
>>> R = range(1,11)
>>> print(R[5])
6
Run Code Online (Sandbox Code Playgroud)
既然R[5]没有存储在内存中,是否每次都通过创建一个新的迭代器来计算?如果没有,如何索引范围对象?
此处没有创建迭代器,也不会发生迭代.range实现该对象使得Python R[5]在恒定时间内计算按需的值.1
如果索引i不是负数,则计算结果为:
i * step + start
Run Code Online (Sandbox Code Playgroud)
因此,对于您的代码R[5],这将5*1 + 1是6.
如果索引i为负数,则将length的长度R添加到ifirst,然后像以前一样计算该值:
(i + len(R)) * step + start
Run Code Online (Sandbox Code Playgroud)
当你编写时R[5],这个Python语法最终被转换为一个调用PyObject_GetItem,它检查对象R以查看它应该如何继续在索引5处找到项目.
PyObject_GetItem首先检查该类型的tp_as_mapping插槽range.这不是空的; 它包含对一个名为的结构的引用range_as_mapping.PyObject_GetItem然后检查以查看此结构mp_subscript字段中的内容:
static PyMappingMethods range_as_mapping = {
(lenfunc)range_length, /* mp_length */
(binaryfunc)range_subscript, /* mp_subscript */
(objobjargproc)0, /* mp_ass_subscript */
};
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码段中所看到的,它会找到range_subscript占据该mp_subscript字段的函数.2
现在range_subscript检查传递的参数(R和5)以确定是否请求了单个索引或切片.整数5意味着只需要一个索引,因此函数将值的计算委托给compute_range_item.此函数执行计算以返回整数6,如本答案第一部分所述.
1我假设您正在使用CPython:其他Python实现可能以range不同方式实现该对象.
2如果你要打电话len(R),你可以看到调用的内部函数mp_length来计算长度R(参见为什么在Python 3中为什么"1000000000000000在范围内(1000000000000001)"这么快?).
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |