将bytearray转换为bytes是否会产生拷贝?

11

将可变类型 bytearray 转换为不可变类型 bytes 是否会产生复制?是否与此相关的成本,还是解释器只是将其视为不可变字节序列,就像在 C++ 中将 char* 强制转换为 const char* const 一样?

ba = bytearray()
ba.extend("some big long string".encode('utf-8'))

# Is this conversion free or expensive?
write_bytes(bytes(ba))

在Python 3中,bytes是其自己的类型,在Python 2.7中,bytes只是str的别名,这两者有区别吗?


所有操作都涉及某些成本。你可以查看源代码,也可以使用时序测试来判断时间是否随问题规模呈线性增长(如果进行了复制,则会出现这种情况)。 - John Coleman
1
我相当确定将bytearray转换为bytes会产生一份拷贝。这是因为如果新的bytes指向与bytearray相同的后备数组,那么它就不是真正不变的。 - Nayuki
2
注意,如果你希望在不复制数据的情况下查看bytearray的内容,你可以使用memoryview来实现。但需要注意的是,对于bytearray数据的修改将会改变memoryview中的数据,并且只要存在导出的缓冲区(其中memoryview是Python代码中创建的最常见类型),bytearray就无法调整大小(无法使用appendpop、重新分配切片等)。 - ShadowRanger
在Python 2中,您还可以使用buffer()bytearray转换为只读缓冲区,而无需执行复制操作。 - pallgeuer
2个回答

20
新的bytes对象被创建,bytesarray和新的bytes对象之间不共享缓冲区,无论是在Python 2还是3中都是如此。
由于bytesarray对象仍可能被引用并改变值,因此不能共享它。
有关详细信息,请参见bytesobject.c源代码。在那里,使用缓冲协议来创建数据的副本(通过PyBuffer_ToContiguous())。

9

Martjin说得对。我只是想通过cpython源代码来支持那个答案。

查看这里的bytes源代码,首先调用bytes_new,它将调用PyBytes_FromObject,后者将调用_PyBytes_FromBuffer,创建一个新的bytes对象并调用PyBuffer_ToContiguous(定义在这里),该函数调用buffer_to_contiguous,这是一个内存复制函数。该函数的注释如下:

将src复制到连续表示中。order是'C'、'F'(Fortran)或'A'(任意)之一。假设:src具有PyBUF_FULL信息,src->ndim >= 1,len(mem) == src->len。

因此,通过bytearray参数调用bytes将会复制数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接