gpt4 book ai didi

python - Python中的memoryview到底是什么?

转载 作者:IT老高 更新时间:2023-10-28 21:43:41 26 4
gpt4 key购买 nike

查看documentation在内存 View 上:

memoryview objects allow Python code to access the internal data of an object that supports the buffer protocol without copying.

class memoryview(obj)

Create a memoryview that references obj. obj must support the buffer protocol. Built-in objects that support the buffer protocol include bytes and bytearray.

然后我们给出示例代码:

>>> 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中怎么做?

人们建议解决方法,例如许多字符串和正则表达式函数占据位置可用于模拟推进指针的参数。这有两个问题:第一这是一种解决方法,你被迫改变你的编码风格来克服缺点,并且第二:并非所有函数都有位置参数,例如正则表达式函数和 startswith 有,encode()/decode() 没有。

其他人可能会建议以 block 的形式加载数据,或者以较小的方式处理缓冲区大于最大 token 的段。好的,所以我们知道这些可能的解决方法,但我们应该在 python 中以更自然的方式工作试图改变编码风格以适应语言 - 不是吗?

编辑2:

代码示例会让事情变得更清楚。这就是我想要做的事情,而且我认为 memoryview 乍一看会让我做的事情。让我们为我正在寻找的功能使用 pmview(正确的内存 View ):

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

最佳答案

memoryview 有用的一个原因是它们可以在不复制底层数据的情况下进行切片,这与 bytes/str 不同。

以下面的玩具为例。

import time
for n in (100000, 200000, 300000, 400000):
data = b'x'*n
start = time.time()
b = data
while b:
b = b[1:]
print(f' bytes {n} {time.time() - start:0.3f}')

for n in (100000, 200000, 300000, 400000):
data = b'x'*n
start = time.time()
b = memoryview(data)
while b:
b = b[1:]
print(f'memoryview {n} {time.time() - start:0.3f}')

在我的电脑上,我得到了

     bytes 100000 0.211
bytes 200000 0.826
bytes 300000 1.953
bytes 400000 3.514
memoryview 100000 0.021
memoryview 200000 0.052
memoryview 300000 0.043
memoryview 400000 0.077

您可以清楚地看到重复字符串切片的二次复杂度。即使只有 400000 次迭代,它已经无法管理。同时,memoryview 版本具有线性复杂度,速度极快。

编辑:请注意,这是在 CPython 中完成的。 There was a bug in Pypy up to 4.0.1 that caused memoryviews to have quadratic performance.

关于python - Python中的memoryview到底是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18655648/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com