Python的底层机制';s记忆视图

Python的底层机制';s记忆视图,python,cpython,memoryview,Python,Cpython,Memoryview,据说Python的memoryview在切片时不会复制数据。许多基准测试已经完成,其中一些测试“证明”了这种行为 在试图和他们捣乱时,我遇到了一个我无法解释的奇怪行为: >>> arr = bytearray(range(0,15)) >>> mem = memoryview(arr) >>> mem[5:15] = mem[0:10] >>> arr bytearray(b'\x00\x01\x02\x03\x04\x00

据说Python的memoryview在切片时不会复制数据。许多基准测试已经完成,其中一些测试“证明”了这种行为

在试图和他们捣乱时,我遇到了一个我无法解释的奇怪行为:

>>> arr = bytearray(range(0,15))
>>> mem = memoryview(arr)
>>> mem[5:15] = mem[0:10]
>>> arr
bytearray(b'\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04\x05\x06\x07\x08\t')
一方面,memoryview“不”复制数据。另一方面,这非常有效

虽然我很高兴它“起作用”,但它起作用的事实让我很难过。好。。。因为它不应该

如果Python有一个1个字符的缓冲区,结果应该是:

bytearray(b'\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04')
基本上,在写第五个字符时,它应该重叠并读取前面写的第一个字符。这种天真方法的一个例子是:

>>> for i in range(10):
...    m[i+5] = m[i]
>>> a
bytearray(b'\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04\x00\x01\x02\x03\x04')
我尝试将memoryview的大小增加到很大的数量,但它仍然有效,这意味着python在后台复制数据,使得memoryview对象变得毫无意义

这里有我错的地方吗?有什么解释吗?那么memoryview是如何工作的呢?

if(dptr+size

memmove
对于重叠的源和目标是安全的。它如何确保安全性因案例和实施而异,但有一种技术是,如果从左到右覆盖尚未复制的数据,则从右到左而不是从左到右进行操作。

男孩,你真快。不过,这也提出了另一个问题:为什么不总是使用memmove?memmove已经对重叠进行了检查,为什么要检查两次?检查两次不是效率更低吗?我相信memmove会求助于memcopy,如果它不重叠的话。也许是因为新的堆栈帧开销?@Bharel:Dunno。如果
dptr
sptr
没有指向同一个数组,那么他们进行的检查甚至是未定义的行为,因此看起来他们真的应该将检查留给
memmove
,后者可以在不使用UB的情况下执行检查。也许他们测量了一些实现的实际性能差异,或者他们只是不信任memmove。可能是某些编译器内联了memcpy,而不是memmove。如果它们不指向同一个数组,则超出了大小界限(前面已经检查过),因此它将求助于memcpy。@Bharel:CPython源代码位于。大多数内置对象类型都是在目录下实现的,其中的文件中,最突出的一个听起来像是实现了
memoryview
…从这里开始,熟悉C API和相关的命名和注释约定就指向了实现memoryview切片分配的函数(以及其他的下标赋值),从这里开始,就需要跟踪代码路径,直到数据复制发生的地方。
    if (dptr + size < sptr || sptr + size < dptr)
        memcpy(dptr, sptr, size); /* no overlapping */
    else
        memmove(dptr, sptr, size);