核心要点
- Python 3 的默认编码是 Unicode:这是最关键的一点,从 Python 3 开始,字符串(
str)类型在内存中默认就是以 Unicode 编码存储的,你不需要做任何特殊设置,就可以直接在代码中写入中文、日文等。 - 列表可以存储任何类型的数据:列表可以存储整数、浮点数、布尔值,当然也包括 Unicode 字符串。
- 编码 vs. 解码:当你的 Python 程序需要与外部世界交互时(将字符串写入文件、通过网络发送、在控制台打印),就需要考虑编码问题。
- 编码:将 Unicode 字符串(
str)转换成字节序列(bytes),以便存储或传输。 - 解码:将字节序列(
bytes)转换回 Unicode 字符串(str),以便程序处理。
- 编码:将 Unicode 字符串(
在 Python 3 中创建包含 Unicode 字符串的列表
在 Python 3 中,直接写字符串字面量,它就是 Unicode 字符串。

# 创建一个包含多种语言的列表
my_unicode_list = [
"你好,世界!", # 中文
"こんにちは", # 日文
"안녕하세요", # 韩文
"Hello, World!", # 英文
"😊" # 表情符号 (也是 Unicode 字符)
]
# 访问列表中的元素
print(my_unicode_list[0]) # 输出: 你好,世界!
print(my_unicode_list[4]) # 输出: 😊
# 遍历列表
for item in my_unicode_list:
print(item)
输出:
你好,世界!
こんにちは
안녕하세요
Hello, World!
😊
你好,世界!
こんにちは
안녕하세요
Hello, World!
😊
你会发现,这一切都非常自然,没有出现任何乱码,这是因为 Python 3 内部已经帮你处理好了。
编码与解码:当列表需要“离开”Python 内存时
当你需要将列表中的字符串保存到文件或发送到网络时,就必须进行编码,因为文件和网络的底层只能处理二进制数据(bytes)。
将列表写入文件
假设我们想把上面的 my_unicode_list 写入一个名为 data.txt 的文件。

错误的做法(会引发 TypeError)
my_unicode_list = ["你好", "世界"]
# 尝试直接将字符串列表写入二进制模式文件会报错
with open('data.txt', 'wb') as f: # 'wb' 表示以二进制写入模式打开
f.write(my_unicode_list) # TypeError: write() argument must be str, not list
即使我们修复 list 的问题,直接写一个字符串也会报错:
my_unicode_list = ["你好", "世界"]
# 尝试将字符串写入二进制模式文件也会报错
with open('data.txt', 'wb') as f:
f.write(my_unicode_list[0]) # TypeError: a bytes-like object is required, not 'str'
这个错误提示很明确:'wb' 模式需要 bytes 对象,但你给了它一个 str 对象。
正确的做法:先编码,再写入

我们需要先将列表中的每个字符串元素编码成 bytes。
my_unicode_list = ["你好", "世界"]
# 1. 定义一个编码,通常推荐使用 'utf-8',因为它能表示所有 Unicode 字符
encoding_type = 'utf-8'
# 2. 将列表中的每个字符串编码成 bytes,并创建一个新列表
bytes_list = [s.encode(encoding_type) for s in my_unicode_list]
# 3. 将 bytes_list 写入文件(使用 'wb' 模式)
with open('data.txt', 'wb') as f:
for line in bytes_list:
f.write(line)
f.write(b'\n') # 写入换行符,bytes 类型的换行符是 b'\n'
print("数据已成功写入 data.txt")
验证:读取文件时需要解码
我们读取这个文件时,需要从 bytes 解码回 str。
# 1. 以二进制模式 ('rb') 读取文件,得到的是 bytes 对象
with open('data.txt', 'rb') as f:
lines_from_file = f.readlines()
# 2. 将每一行 bytes 解码回 str
decoded_list = [line.strip().decode(encoding_type) for line in lines_from_file]
print("从文件读取并解码后的列表:")
print(decoded_list)
输出:
从文件读取并解码后的列表:
['你好', '世界']
可以看到,数据完美地保存和恢复了。
常见的编码问题
问题1:使用了错误的编码
如果你在编码时使用 gbk(一种主要用于简体中文的编码),而你的字符串里包含了日文或表情符号,程序就会抛出 UnicodeEncodeError。
my_unicode_list = ["你好", "こんにちは"]
# 尝试用 'gbk' 编码包含日文的字符串
try:
encoded_bytes = "こんにちは".encode('gbk')
except UnicodeEncodeError as e:
print(f"编码错误: {e}")
# 输出: 编码错误: 'gbk' codec can't encode character '\u3053' in position 0: illegal multibyte sequence
解决方案:始终使用 utf-8 除非你有特殊需求(比如与一个只支持 gbk 的旧系统交互)。
问题2:读取文件时使用了错误的编码
如果你用 utf-8 去读取一个用 gbk 编码的文件,你会得到 UnicodeDecodeError。
假设 data_gbk.txt 文件是用 gbk 编码保存的 "你好"。
# 假设 data_gbk.txt 是用 'gbk' 编码保存的 "你好"
# 尝试用 'utf-8' 去解码
try:
with open('data_gbk.txt', 'rb') as f:
content = f.read().decode('utf-8')
except UnicodeDecodeError as e:
print(f"解码错误: {e}")
# 输出: 解码错误: 'utf-8' codec can't decode byte 0xc4 in position 0: invalid start byte
解决方案:你需要知道文件的原始编码,并使用相同的编码来解码。
总结与最佳实践
- Python 3 内部是 Unicode:在程序内部处理字符串时,你无需担心编码问题,直接使用
str类型即可。 - 列表存储 Unicode 字符串:列表可以无缝地存储各种语言的 Unicode 字符串。
- I/O 操作需要编码:当涉及文件读写、网络请求等与外部交互的操作时,必须进行编码和解码。
- 写入:
str->.encode('utf-8')->bytes-> 写入文件/网络 - 读取:从文件/网络读取 ->
bytes->.decode('utf-8')->str
- 写入:
- 统一使用 UTF-8:在不确定的情况下,
utf-8是最安全、最现代的选择,它能表示地球上几乎所有的字符,并且是事实上的标准。 - 处理异常:在编码和解码时,最好使用
try...except块来捕获UnicodeEncodeError和UnicodeDecodeError,让你的程序更健壮。
