给妹子讲python-S01E08理清python中的字符编码方法

简介: 本文介绍python中编、解码的本质是文本字符串和字节字符串的相互转换、python中编、解码方法举例及过程解析、unicode、latin-1、ASCII编码方式的兼容性问题、读取二进制文件。

上一集讲清楚字符编码的基础概念后我相信这一集再来介绍python中的字符编码就会容易的多。

通过上一集我们知道ASCII码包括其最常见的超集Latin-1依赖这样的一个假设即每一个字符与一个字节相匹配由于存在太多的字符因此不可避免的会出现问题Unicode字符集通过使用4个字节来表示1个字符则解决了该问题。

首先来介绍一下Python中的两种字符串

Python中有两种字符串文本字符串和字节字符串。其中文本字符串类型被命名为str内部采用Unicode字符集兼容ASCII码而字节字符串则直接用来表示原始的字节序列用print函数来打印字节字符串时若字节在ascii码范围内则显示为ascii码对应的字符其余的则直接显示为16进制数该类型被命名为bytes。

看一个简单的例子

s = 'apple'
b = b'apple'
print(b)
print(type(b))
print(s)
print(type(s))

b'apple'
<class 'bytes'>
apple
<class 'str'>

再近距离的看看bytes类型字节字符串本质上它就是一串单字节16进制数

b = b'apple'
print(b[0])
print(b[1:])
print(list(b))

97
b'pple'
[97, 112, 112, 108, 101]

【妹子说】那这和编码、解码有何关联呢

从本质上来说编码和解码就是str和bytes这两种字符串类型之间的互相转换。

str包含一个encode方法使用特定编码将该字符串其转换为一个bytes这称之为编码。bytes类包含了一个decode方法也接受一个编码作为单个必要参数并返回一个str这称之为解码。这种转换操作是显式的操作且必须根据数据被编码时采用的编码类型进行解码。

首先说说编码即将unicode的str文本字符串转换为bytes的字节字符串可以显式的传入指定编码一般来说采用utf-8编码或使用平台的默认编码。

s = 'π排球の'
b1 = s.encode('utf-8')
b2 = s.encode()
print(b1)
print(b2)

b'\xcf\x80\xe6\x8e\x92\xe7\x90\x83\xe3\x81\xae'
b'\xcf\x80\xe6\x8e\x92\xe7\x90\x83\xe3\x81\xae'

那么我们看看在不写编码的时候平台默认的编码方式到底是什么

import sys

print(sys.platform)
print(sys.getdefaultencoding())

win32
utf-8

可以看出我这个平台默认选择的是utf-8编码方式。

接下来我们来比较一下unicode、latin-1、ASCII编码方式的兼容性问题:

首先非ASCII字符无法使用ASCII编码转换成字节字符串

s = 'π排球の'
b = s.encode('ascii')

Traceback (most recent call last):
 File "E:/12homework/12homework.py", line 2, in <module>
   b = s.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3:
 ordinal not in range(128)

其次Latin-1和unicode编码方式不兼容。

例如重音字符会在latin-1字符集和unicode字符集中同时存在但是通过latin-1和unicode编码方式编出来的字节流是不一样的注意虽然unicode字符集是包含了latin-1字符集但是不代表utf-8编码方式兼容latin-1编码方式。因为unicode字符集中除了ascii字符集外都是采用多字节的编码方式而latin-1一律采用单字节的方式

s = 'Äè'
print(s.encode('utf-8'))
print(s.encode('latin-1'))

b'\xc3\x84\xc3\xa8'
b'\xc4\xe8'

只有ascii字符集中的字符三种编码方式得到的结果才完全一致。对unicode进行编码的时候针对常规的7位ASCII文本由于utf-8以及latin-1编码方式都是兼容ASCII的所以结果都是一样的。

s = 'abc'
print(s.encode('utf-8'))
print(s.encode('latin-1'))
print(s.encode('ascii'))

b'abc'
b'abc'
b'abc'

【妹子说】那对应的再来谈谈decode解码方法吧。

将bytes类型字符串转换成str类型的unicode文本字符串也是一样要么指定编码参数要么使用平台的默认参数。这个例子中我们要操作的字节字符串b是通过utf-8编码方式对文本字符串'π排球の'编码而形成的。

b = b'\xe6\x8e\x92\xe7\x90\x83'
s1 = b.decode(encoding='utf-8')
s2 = b.decode()
s3 = b.decode(encoding='latin-1')

print(s1)
print(s2)
print(s3)

排球
排球
排çƒ

值得注意的是最后一行代码想通过latin-1解码字节字符串由于字节字符串是通过utf-8编码形成因此这样解码形成得到的只能是乱码。

Utf-8编码是用两个字节来表示非ASCII的高128字符而latin-1则是用一个字节来一一对应

【妹子说】计算机用二进制来存储信息而却能在各种应用中显示我们需要的文字这应该是字符编、解码的应用吧。

很对下面我们来说说文本文件读取时的编、解码问题

当一个文件以文本模式打开的时候被读取的二进制存储数据也就是存储的字节字符串会自动被解码依据显式提供的编码名称或平台默认的编码名称并且将其返回为一个str。写入文件时会接受一个str并且将其传输到文件之前自动编码成字节字符串以供磁盘存储。

当一个文件以二进制模式打开时需要在open方法的模式字符串参数里添加一个b此时读取的数据不会以任何方式解码而是直接返回其原始内容即一个bytes对象写入文件时接受一个bytes对象并且将其传送到文件中且不进行修改。

在读取文本文件的时候如果open函数没有声明他们如何编码python3会因其所运行的系统而选取默认的编码方式默认情况下python3 期望文件使用 utf-8进行编码。但由于文件并不总是在同一个系统中被保存和打开因此会带来乱码的风险所以我们需要显式的指定编码。

补充的说明一下可以很简单的进行一个分类处理图像文件、设备数据流等可以使用bytes和二进制模式文件处理而如果要处理的内容实质是文本的内容例如程序输出、HTML、国际化文本或CSV或XML文件则可能要使用str和文本模式文件

例如我们先把AÄBèC用UTF-8编码后存入utf-8data文件再来读取他具体看看这里是如何实现的。

s = 'AÄBèC'

with open('utf-8data','w',encoding='utf-8') as f:
   f.write(s)

with open('utf-8data','r',encoding='utf-8') as f:
   u_str = f.read()
print(u_str)


AÄBèC

这里用到的文件读写的方法后面的章节会详细介绍现在知道他是什么就好了。

以二进制的形式读取文件。

还有一种我们之前介绍过的用法文本字符串在存储到磁盘的时候会编码成字节字符因此我们也可以先以字节字符串的形式从文件中将其读取然后再进行解码。

这样做的原因有二一种是所接收的可能是非文本数据如一个图像文件另一个潜在原因是无法确定所读取文本文件的编码可能需要依据其他信息再确定

with open('utf-8data', 'rb') as f:
   byte_str = f.read()

print(byte_str)
print(byte_str.decode(encoding='utf-8'))

b'A\xc3\x84B\xc3\xa8C'
AÄBèC

字符串编、解码在python中很重要特别是在网络爬虫等网络应用程序中在后面的实际应用中会感受到他的作用会越来越明显。

【妹子说】这一集的内容很多细致剖析了python中的两种字符串类型和编、解码的处理方法。再结合之前的三集就能从基本使用、字符编、解码的维度闭环出一个完整的知识网络了收获很大。

原文发布时间为2018-08-06
本文作者酱油哥
本文来自云栖社区合作伙伴“ Python爱好者社区”了解相关信息可以关注“ Python爱好者社区

相关文章
|
2月前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
55 0
|
1月前
|
机器学习/深度学习 Python
堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能
本文深入探讨了堆叠集成策略的原理、实现方法及Python应用。堆叠通过多层模型组合,先用不同基础模型生成预测,再用元学习器整合这些预测,提升模型性能。文章详细介绍了堆叠的实现步骤,包括数据准备、基础模型训练、新训练集构建及元学习器训练,并讨论了其优缺点。
57 3
|
2月前
|
测试技术 API Python
【10月更文挑战第1天】python知识点100篇系列(13)-几种方法让你的电脑一直在工作
【10月更文挑战第1天】 本文介绍了如何通过Python自动操作鼠标或键盘使电脑保持活跃状态,避免自动息屏。提供了三种方法:1) 使用PyAutoGUI,通过安装pip工具并执行`pip install pyautogui`安装,利用`moveRel()`方法定时移动鼠标;2) 使用Pymouse,通过`pip install pyuserinput`安装,采用`move()`方法移动鼠标绝对位置;3) 使用PyKeyboard,同样需安装pyuserinput,模拟键盘操作。文中推荐使用PyAutoGUI,因其功能丰富且文档详尽。
|
21天前
|
安全
Python-打印99乘法表的两种方法
本文详细介绍了两种实现99乘法表的方法:使用`while`循环和`for`循环。每种方法都包括了步骤解析、代码演示及优缺点分析。文章旨在帮助编程初学者理解和掌握循环结构的应用,内容通俗易懂,适合编程新手阅读。博主表示欢迎读者反馈,共同进步。
|
28天前
|
JSON 安全 API
Python调用API接口的方法
Python调用API接口的方法
148 5
|
1月前
|
算法 决策智能 Python
Python中解决TSP的方法
旅行商问题(TSP)是寻找最短路径,使旅行商能访问每个城市一次并返回起点的经典优化问题。本文介绍使用Python的`ortools`库解决TSP的方法,通过定义城市间的距离矩阵,调用库函数计算最优路径,并打印结果。此方法适用于小规模问题,对于大规模或特定需求,需深入了解算法原理及定制策略。
43 15
WK
|
1月前
|
Python
Python中format_map()方法
在Python中,`format_map()`方法用于使用字典格式化字符串。它接受一个字典作为参数,用字典中的键值对替换字符串中的占位符。此方法适用于从字典动态获取值的场景,尤其在处理大量替换值时更为清晰和方便。
WK
93 36
|
1月前
|
机器学习/深度学习 人工智能 算法
强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用
本文探讨了强化学习在游戏AI中的应用,从基本原理、优势、应用场景到具体实现方法,以及Python在其中的作用,通过案例分析展示了其潜力,并讨论了面临的挑战及未来发展趋势。强化学习正为游戏AI带来新的可能性。
107 4
|
1月前
|
Python
Python编程中的魔法方法(Magic Methods)
【10月更文挑战第40天】在Python的世界中,魔法方法就像是隐藏在代码背后的神秘力量。它们通常以双下划线开头和结尾,比如 `__init__` 或 `__str__`。这些方法定义了对象的行为,当特定操作发生时自动调用。本文将揭开这些魔法方法的面纱,通过实际例子展示如何利用它们来增强你的类功能。
22 1
|
1月前
|
人工智能 Shell 开发工具
[oeasy]python0041_输出ASCII码表_英文字符编码_键盘字符_ISO_646
本文介绍了ASCII码表的生成与使用,包括英文字符、数字和符号的编码。通过Python代码遍历0到127的ASCII值,解决了找不到竖线符号的问题,并解释了ASCII码的固定映射关系及其重要性。文章还介绍了ASCII码的历史背景,以及它如何成为国际标准ISO 646。最后,通过安装`ascii`程序展示了完整的ASCII码表。
26 1