__bytes__ 方法必须返回 bytes 类型,否则抛出 typeerror;它专用于提供对象的规范字节表示(如网络传输),不用于序列化或格式化,且不被 pickle/json 自动调用。

__bytes__ 方法必须返回 bytes 类型,否则会报 TypeError
Python 的 __bytes__ 方法不是可选的“增强序列化”,而是明确要求返回 bytes 实例的协议方法。一旦定义了它,调用 bytes(obj) 就会触发该方法;如果返回值不是 bytes(比如 str、bytearray 或 list),Python 会直接抛出 TypeError: __bytes__ returned non-bytes object。
- 常见错误:在方法里写
return self.data.encode('utf-8')—— 看似合理,但如果self.data是数字、None 或非字符串类型,就会崩溃 - 正确做法:确保所有分支最终都走
bytes()构造或字面量,例如b''、struct.pack(...)、json.dumps(...).encode() - 注意:不能返回
bytearray,哪怕它和bytes行为相似,也必须显式转换:return bytes(my_bytearray)
__bytes__ 和 __str__ / __repr__ 的用途完全不同
__bytes__ 不是 __str__ 的二进制版本,也不是为了“打印好看”。它的语义是:提供该对象在网络传输、文件写入或底层协议中所需的**规范字节表示**。比如你有一个自定义的 IP 地址类,__bytes__ 应该返回 4 字节(IPv4)或 16 字节(IPv6)的原始数据,而不是 b'192.168.1.1' 这种可读字符串。
- 场景举例:实现一个轻量级二进制消息头类,字段顺序固定,
__bytes__直接用struct.pack('>IHI', self.magic, self.version, self.length) - 反例:对日志类、配置类定义
__bytes__并返回 JSON 字节流——这属于序列化逻辑,更适合用json.dumps().encode()显式调用,而非绑定到bytes()协议 - 兼容性提示:Python 3.10+ 对
__bytes__返回值做了更严格的类型检查,旧代码若隐式返回bytearray可能突然失效
__bytes__ 不会自动被 pickle 或 json 使用
很多人误以为实现了 __bytes__ 就能让 pickle.dump() 或 json.dump() 自动生效,其实完全不会。pickle 走的是自己的协议(__getstate__、__reduce__ 等),json 只认 dict、list、基本类型和 default 参数指定的转换函数。
- 如果你希望 pickle 时用字节表示,得单独实现
__reduce__,例如返回(bytes, (self,))(前提是self确实支持__bytes__) - 想让 json 支持,得配
default=lambda obj: obj.__bytes__().hex() if hasattr(obj, '__bytes__') else None,但要注意 hex 编码后已不是原始字节 - 真正依赖
__bytes__的标准操作只有:bytes(obj)、socket.send(obj)(如果 obj 是自定义类)、io.BufferedIOBase.write(obj)
继承内置类型时小心 __bytes__ 的继承行为
如果你的类继承自 int、str 或 bytes,Python 可能跳过你的 __bytes__ 方法。比如子类 class MyInt(int): def __bytes__(self): return b'custom',调用 bytes(MyInt(42)) 仍返回 b'\x00\x00\x00*'(即 int 的默认行为),因为 int 已经实现了 __bytes__ 且不委托给子类。
- 验证方式:打印
MyInt.__bytes__.__func__,如果指向int.__bytes__而不是你自己定义的方法,说明被覆盖了 - 绕过办法:不要继承数值类型来“伪装”字节行为;改用组合(has-a)而非继承(is-a),或者显式在需要处调用
your_obj.to_bytes()这类自定义方法 - 例外:继承
object安全,所有用户定义类默认没有__bytes__,你的实现会被尊重
__bytes__ 是个契约,不是便利函数。它只服务于明确需要字节流的上下文,别把它当成通用序列化入口。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











