为非C程序员解释缓冲区和内存视图对象
Python 2.7 引入了一种新的 API,用于处理缓冲区和内存视图对象。
我看了相关的文档,觉得我理解了基本概念(就是以原始的形式访问对象内部的数据,而不需要复制,这样可以更快并且占用更少的内存),但要真正理解这些文档,读者需要有比我更深入的 C 语言知识。
如果有人能花时间来:
- 用简单易懂的语言解释一下缓冲区和内存视图对象,
- 描述一个使用缓冲区和内存视图对象的场景,为什么这样做是“更符合 Python 风格”的方式,
2 个回答
我找到的部分答案是,buffer
是一种“旧方法”,而 memoryview
是新的方法,不过它被移植到了 2.7 版本 - 你可以在这个归档的博客中查看详细信息 这里
不过这并没有回答我为什么我认为在 2.7 中实现的 C API 让我可以构造一个 buffer
,却不能构造一个 memoryview
的问题...
要让 memoryview
在 Python 2.7 中正常工作,你需要在 tp_flags
中设置 Py_TPFLAGS_HAVE_NEWBUFFER
这个标志。我发现内置的 bytearray
源代码是个很好的参考;它在 Include/bytearrayobject.h
和 Objects/bytearrayobject.c
中。
这是我写的一个哈希函数中的一行代码:
M = tuple(buffer(M, i, Nb) for i in range(0, len(M), Nb))
这段代码会把一个很长的字符串M分割成更短的“字符串”,每个短字符串的长度是Nb,Nb是我一次能处理的字节数或字符数。它这样做是不会复制字符串的任何部分的,如果我像这样切片字符串的话,就会发生复制:
M = tuple(M[i*Nb:i*Nb+Nb] for i in range(0, len(M), Nb))
现在,我可以像切片一样遍历M:
H = key
for Mi in M:
H = encrypt(H, Mi)
简单来说,缓冲区和内存视图是处理Python中字符串不可变性和切片等操作的一般复制行为的高效方法。内存视图就像一个缓冲区,不同的是你不仅可以读取它,还可以写入。
虽然主要的缓冲区/内存视图文档是关于C语言实现的,但标准类型页面在内存视图下有一些信息:http://docs.python.org/library/stdtypes.html#memoryview-type
编辑:我在书签中找到了这个,http://webcache.googleusercontent.com/search?q=cache:Ago7BXl1_qUJ:mattgattis.com/2010/3/9/python-memory-views+site:mattgattis.com+python&hl=en&client=firefox-a&gl=us&strip=1 是一个非常好的简要介绍。
编辑2:结果我最初是从什么时候应该使用内存视图?这个问题中找到那个链接的,那个问题从来没有详细回答过,而且链接也失效了,希望这能有所帮助。