来自生成器的 Python 字节对象

Jer*_*imo 7 python arrays generator python-3.x

假设我有一个像

gen = (i*2 for i in range(100))
Run Code Online (Sandbox Code Playgroud)

我现在想创建一个包含生成器产生的所有值的字节对象。我可以执行以下操作:

b = bytes(gen)
Run Code Online (Sandbox Code Playgroud)

我现在的问题是:由于bytes对象是不可变的,在这种情况下内存分配如何工作?我是否必须假设对于生成器产生的每个元素,都会bytes创建一个新对象,并将先前的内容加上另一个元素复制到其中?这将是非常低效的,尤其是对于更大长度的生成器。而且由于生成器不提供任何长度信息,似乎没有任何其他方式可以在内部预先分配所需的内存。

再说一次,在尽可能少的内存使用情况下,实现这一目标的更好方法是什么?如果我先使用(可变的)bytearray并将其转换为bytes对象?

b = bytes(bytearray(gen))
Run Code Online (Sandbox Code Playgroud)

甚至是一个清单?

b = bytes(list(gen))
Run Code Online (Sandbox Code Playgroud)

但这看起来有点奇怪和违反直觉......


背景:我使用的特定生成器通过来自另一个模块 (.pyd) 的 C-API 一次读取一个字节(作为 0..255 中的 Python 整数),并且序列的总长度事先已知,向上到那里的 2**25 个字节。我的读出函数应该收集这些并返回一个bytes我认为合适的对象,因为数据是只读的。

int*_*ath 5

bytes(iterator)使用内部 C-API_PyBytes_FromIterator函数从迭代器创建字节对象,该函数使用特殊_PyBytes_Writer协议。它内部使用一个缓冲区,当它使用规则溢出时调整大小:

bufsize += bufsize  / OVERALLOCATE_FACTOR
Run Code Online (Sandbox Code Playgroud)

对于 linux OVERALLOCATE_FACTOR=4,对于 windows OVERALLOCATE_FACTOR=2。

那些。这个过程看起来像写入 RAM 中的文件。最后,缓冲区的内容返回。