Python 3 的 str 就是 Unicode 字符序列,本质是文本类型;Python 2 的 str 是字节序列,无编码语义,二者类型语义不同、不可隐式转换,必须通过 encode/decode 显式转换。

str 在 Python 3 中就是 Unicode 文本,不是“用了 Unicode 编码”,而是它**根本就是 Unicode 字符序列**——这是类型语义层面的设计变更,不是靠改配置能绕过去的。
Python 2 的 str 是字节容器,不带编码含义;Python 3 的 str 是文本容器,天然承载字符意义。两者不可互换,也不能隐式转换。
Python 2 的 str 本质是 bytes
写 s = "中文",Python 2 实际存的是源文件保存时的原始字节(比如 UTF-8 的 b'\xe4\xb8\xad\xe6\x96\x87'),解释器不认为它是“中文”,只当它是几个无意义的字节。
想当文本用?必须显式 s.decode('utf-8') 得到 unicode 对象。
漏掉这步,拼接、正则、打印都可能触发 UnicodeDecodeError。
Python 3 的 str 天然是 Unicode 码点序列
s = "中文" → s 是 str 类型,值为两个 Unicode 码点 U+4E2D 和 U+6587,和源文件怎么保存无关。
要写入文件或发 HTTP 请求?必须显式 s.encode('utf-8') 得到 bytes。
从网络或文件读出二进制内容?得到的是 bytes,得按真实编码 b.decode('gbk') 才能变 str。
错误示例:"abc" + b"def" → 直接报 TypeError: can't concatenate str and bytes。
open() 默认行为差异导致实际乱码最频繁
Python 3 的 open() 默认用系统 locale 解码,但 locale 不等于文件真实编码:
• Linux/macOS 下常是 UTF-8,读 UTF-8 文件没问题
• Windows 中文系统 locale 常是 GBK,读 UTF-8 文件就崩
正确做法永远显式指定:open("data.txt", encoding="utf-8") 或 open("data.txt", "rb")(返回 bytes,再按需解码)sys.getdefaultencoding() 完全无关——它只控制 Python 2 风格的隐式转换,Python 3 中已禁用。
真正难的不是怎么转,是怎么猜
bytes 没有自我描述能力。b'\xe4\xb8\xad' 可能是 UTF-8 的“中”,也可能是 GBK 的“涓”。
没有上下文,就没有确定答案;
靠 chardet 这类库探测,也只是概率性猜测,不是真理。
这个判断过程,比写 .encode() 和 .decode() 花的时间多得多。
立即学习“Python免费学习笔记(深入)”;


















