翻译 - Python切片的实现原理
Contents
[TOC]
原文链接: How is slicing implemented in python? 来自 Quora 作者: Vladislav Zorov 翻译理由: 作者在分析切片的原理的同时, 也很详细的说明了如何去看源码, 虽然只有27个赞…
问题: Python 是怎么实现切片的?
答案:
查看源码
|
|
dis 模块支持通过反汇编分析CPython bytecode。反汇编字节码的意思就是接收这一系列的字节,然后打印出我们能够理解的字符(opcodes)。
dis.dis(x=None, *, file=None) 拆卸 x 对象。 x 可以表示模块,类,方法,函数,生成器,代码对象,源代码字符串或原始字节码的字节序列。对于模块,它会拆散所有函数。对于一个类,它反汇编所有的方法(包括类和静态方法)。对于代码对象或原始字节码序列,每个字节码指令打印一行。字符串首先被编译为使用 compile() 内置函数代码对象,然后被反汇编。如果没有提供对象,则此函数将反汇编最后一个回溯。
LOAD_NAME
和 LOAD_CONST
只不过是将一些常量压栈, 有意思的操作码(opcodes)是BUILD_SLICE
和 BINARY_SUBSCR
我们去 CPython 在 GitHub 的镜像库上搜索关键字 BUILD_SLICE
python/cpython - 发现 “compile.c” 和 “ceval.c” 比较因吹思艇; “compile.c” 中是声明, “ceval.c” 中是执行, 我们要看就是后者
我们发现在TARGET(BUILD_SLICE)
里调用了PySlice_New
, 再次返回之前的搜索页面搜索它, 于是我们在 sliceobject.c中找到这货, 不过有点意思的是, 看起来只是一个 “helper class” 来处理索引, 检查 stop 参数是否超出最大值, 切片长度非负等等
所以我们再看看BINARY_SUBSCR
, 这个看起来是由下标a[n]
触发, 下标为栈最顶值, 用于栈次顶值, 所以切片对象是通过下标组成列表对象(BINARY_SUBSCR
将会 pop 3 个LOAD_CONST
, 代码位于 “ceval.c”)
回到之前的 “sliceobject.c”, listobject.c-别被代码量吓着了, 其实挺容易找到这个函数
|
|
在这个函数里边, 有正常的索引获取, 也有我们要找的: 切片
|
|
当步长为 1 (step=1)时的循环, 就很像我们要找的了
so, 别的先不说, 切片列表其实就是个循环. 不过是用 C 循环的, 切片速度比你自己用 Python list.append
循环快多了
对于其他类型可以支持下标切片的对象, 可能原理会有所不同; 例如 range
与 list
就有很大的区别
|
|
range
像是重新计算了起始位置, 步长, 终止位置(start, step, end), 但是啥都没干, 因为已经切过了…(注: Python3 的 range
, 2 里边是 xrange
)
补充拓展
-
caval.c 中的
BINARY_SUBSCR
, POP() 就是LOAD_CONST
的那个栈 pop,PyObject_GetItem(dic, key)
1 2 3 4 5 6 7 8 9 10 11
TARGET(BINARY_SUBSCR) { PyObject *sub = POP(); PyObject *container = TOP(); PyObject *res = PyObject_GetItem(container, sub); Py_DECREF(container); Py_DECREF(sub); SET_TOP(res); if (res == NULL) goto error; DISPATCH(); }
-
实现一个 python3 里的
range
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Myrange: def __init__(self, num): self.i = 0 self.num = num def __iter__(self): return self def __next__(self): if self.i < self.num: i = self.i self.i += 1 return i else: raise StopIteration()
有个缺陷就是Myrange
是一个迭代器, 而Python3 的range
不是, 只是一个惰性的可迭代对象
|
|
使用 next 无法调用 range
|
|
range 是序列(列表,元组和字符串),但并不包含任何内存中的内容
|
|
Author yangly
LastMod 2018-07-27