查看memoryview上的文档:
memoryview对象允许Python代码无需复制即可访问支持缓冲区协议的对象的内部数据。
类memoryview(obj)
创建引用obj的memoryview。obj必须支持缓冲区协议。支持缓冲区协议的内置对象包括字节和字节数组。
然后我们得到了示例代码:
>>> v = memoryview(b'abcefg')
>>> v[1]
98
>>> v[-1]
103
>>> v[1:4]
<memory at 0x7f3ddc9f4350>
>>> bytes(v[1:4])
b'bce'
报价结束,现在让我们仔细看看:
>>> b = b'long bytes stream'
>>> b.startswith(b'long')
True
>>> v = memoryview(b)
>>> vsub = v[5:]
>>> vsub.startswith(b'bytes')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'memoryview' object has no attribute 'startswith'
>>> bytes(vsub).startswith(b'bytes')
True
>>>
所以我从上面收集到了什么:
我们创建一个memoryview对象以暴露缓冲区对象的内部数据而不进行复制,但是,为了对对象执行任何有用的操作(通过调用对象提供的方法),我们必须创建一个副本!
通常,当我们有一个大对象时,将需要memoryview(或旧的缓冲区对象),并且切片也可能很大。如果我们要制作大片或多次制作小片,那么就需要更高的效率。
使用上述方案,除非有人可以向我解释我在这里缺少的内容,否则我看不出它对任何一种情况都有用。
编辑1:
我们有大量数据,我们想通过从头到尾进行处理来处理它,例如从字符串缓冲区的开头提取标记直到缓冲区被消耗。在C术语中,这是通过缓冲区,并且指针可以传递给任何需要缓冲区类型的函数。如何在python中完成类似的操作?
人们提出了解决方法,例如,许多字符串和正则表达式函数采用位置参数,可用于模拟前进的指针。这样做有两个问题:首先是一种解决方法,您不得不更改编码样式以克服缺点,其次,并非所有函数都具有位置参数,例如regex函数,而startswith
do,encode()
/ decode()
not则没有。
其他人可能建议分块加载数据,或在大于最大令牌的小段中处理缓冲区。好的,我们知道了这些可能的解决方法,但是我们应该在python中以更自然的方式工作,而不必尝试弯曲编码样式以适应语言-是不是?
编辑2:
代码示例将使事情变得更清楚。这就是我想要做的,并且我以为memoryview可以让我乍一看。让我们使用pmview(适当的内存视图)来实现我正在寻找的功能:
tokens = []
xlarge_str = get_string()
xlarge_str_view = pmview(xlarge_str)
while True:
token = get_token(xlarge_str_view)
if token:
xlarge_str_view = xlarge_str_view.vslice(len(token))
# vslice: view slice: default stop paramter at end of buffer
tokens.append(token)
else:
break