如何通过Python的bytearray进行原位修改以减少临时对象创建?

云萱大大_7809

云萱大大_7809

2026-06-09

1007人浏览

原创

bytearray支持原位修改,但仅限索引赋值和等长切片赋值;+=、replace()等操作会触发隐式拷贝;memoryview可零成本访问底层内存实现高效查找与修改;应避免decode/encode,直接用字节级整数运算;预分配容量可减少realloc开销。

如何通过python的bytearray进行原位修改以减少临时对象创建?

bytearray 支持原位修改,但必须避开隐式拷贝操作

Python 的 bytearray 确实是可变字节序列,能避免像 bytes 那样每次切片或拼接都生成新对象。但很多人误以为只要用了 bytearray 就自动“零拷贝”——实际中大量操作仍会触发隐式复制,比如 += 拼接、replace()、甚至某些切片赋值。

真正安全的原位修改只发生在明确索引/切片赋值且长度匹配时:

  • ba[i] = 65 —— 安全,单字节写入
  • ba[2:5] = b'xyz' —— 安全,右侧 bytes 长度必须等于切片长度(3)
  • ba[2:5] = bytearray(b'xy') —— 触发 ValueError,因长度不匹配(2 ≠ 3)
  • ba += b'extra' —— 不安全,底层调用 extend(),可能引发内存重分配并拷贝整块数据

用 memoryview 绕过 bytearray 方法的额外开销

很多 bytearray 自带方法(如 find()、index())虽不修改内容,但内部可能构造临时缓冲区或做边界检查,影响热点路径性能。更轻量的方式是用 memoryview 直接访问底层内存:

# 原始 bytearray
ba = bytearray(b'hello world')
mv = memoryview(ba)
<h1>快速查找,不触发任何 bytearray 方法逻辑</h1><p>pos = mv.find(b'world')  # 返回 int,和 bytes.find 行为一致</p><h1>原位修改:直接写入 memoryview 切片</h1><p>mv[0:5] = b'HELLO'  # 此时 ba 已被修改,无新对象
</p>

注意:memoryview 对象本身不持有数据,只引用 bytearray 底层 buffer,所以创建它几乎零成本;但不能对 memoryview 调用 append() 或 extend() 这类会改变长度的操作。

python-parallelization
python-parallelization

将顺序 Python 代码转换为并行/并发实现,用于在需要并行化 Python 代码、提升性能时使用。

下载

避免 decode() / encode() 引入中间字符串对象

如果目标只是解析或填充二进制协议字段(如头部长度、校验和),强行转成 str 再操作,会立刻创建字符串对象并触发 UTF-8 编解码——这完全违背“减少临时对象”的初衷。

应直接用整数运算和字节操作:

  • 写入 4 字节大端整数:ba[8:12] = len(payload).to_bytes(4, 'big')
  • 读取 2 字节小端无符号短整:port = int.from_bytes(ba[12:14], 'little')
  • 计算校验和(XOR 所有字节):checksum = 0; [checksum := checksum ^ b for b in ba[0:16]](注意这是 Python 3.8+ 海象运算符,若需兼容旧版,改用循环)

这些操作全部在原 bytearray 上完成,不产生任何中间 bytes、str 或 int 列表。

resize 要预估容量,避免反复 realloc

bytearray 动态增长时(如 append()、extend()),Python 采用类似 list 的 over-allocation 策略,但频繁小幅扩容仍会导致多次内存拷贝。如果事先知道最终大小,优先用 bytearray(n) 预分配,再用切片赋值填入:

# ❌ 低效:逐字节追加
ba = bytearray()
for b in data_stream:
    ba.append(b)  # 每次可能 realloc + copy
<h1>✅ 高效:预分配后原位写入</h1><p>ba = bytearray(expected_total_len)
offset = 0
for chunk in data_stream:
end = offset + len(chunk)
ba[offset:end] = chunk
offset = end
</p>

预分配的关键在于「预期总长」要尽量准确;高估一点没关系,低估则仍会触发 realloc。另外,bytearray 的初始容量不会自动收缩,所以用完记得手动 del 或复用对象。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

python

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1731

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4404

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1709

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

25817

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3147

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3167

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1183

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2443

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程