在内存 View 中检查documentation:



然后我们得到了示例代码:

>>> 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:

我们有大量的数据,我们希望通过从头到尾逐一处理它来进行处理
最后,例如从字符串缓冲区的开头提取 token 直到缓冲区被使用。在C术语中,这是通过缓冲区前进一个指针,并且可以传递该指针
到任何需要缓冲区类型的函数。如何在python中完成类似的操作?

人们提出了解决方法,例如许多字符串和正则表达式函数占据了上风
可用于模拟前进指针的参数。这有两个问题:第一
这是一种解决方法,您不得不更改编码风格以克服缺点,并且
第二:并非所有函数都有位置参数,例如正则表达式函数和startswith有,encode()/decode()没有。

其他人可能建议分块加载数据,或以较小的速度处理缓冲区
大于最大 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不同,ojit_code可以切片而不复制基础数据。
例如,以以下玩具示例为例。

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

for n in (100000, 200000, 300000, 400000):
    data = 'x'*n
    start = time.time()
    b = memoryview(data)
    while b:
        b = b[1:]
    print 'memoryview', n, time.time()-start
在我的电脑上
bytes 100000 0.200068950653
bytes 200000 0.938908100128
bytes 300000 2.30898690224
bytes 400000 4.27718806267
memoryview 100000 0.0100269317627
memoryview 200000 0.0208270549774
memoryview 300000 0.0303030014038
memoryview 400000 0.0403470993042
您可以清楚地看到重复的字符串切片的二次复杂度。即使只有400000次迭代,它也已经无法处理。同时,memoryview版本具有线性复杂度,并且闪电般快速。
编辑:注意,这是在CPython中完成的。 There was a bug in Pypy up to 4.0.1 that caused memoryviews to have quadratic performance.

10-04 10:59