建设网站 万网,有什么用,长沙微信乘车码在哪里,wordpress用什么图床好转#xff1a; https://www.liaoxuefeng.com/wiki/1016959663602400/1017075323632896
字符编码
我们已经讲过了#xff0c;字符串也是一种数据类型#xff0c;但是#xff0c;字符串比较特殊的是还有一个编码问题。
因为计算机只能处理数字#xff0c;如果要处理文本 https://www.liaoxuefeng.com/wiki/1016959663602400/1017075323632896
字符编码
我们已经讲过了字符串也是一种数据类型但是字符串比较特殊的是还有一个编码问题。
因为计算机只能处理数字如果要处理文本就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特bit作为一个字节byte所以一个字节能表示的最大的整数就是255二进制11111111十进制255如果要表示更大的整数就必须用更多的字节。比如两个字节可以表示的最大整数是655354个字节可以表示的最大整数是4294967295。
由于计算机是美国人发明的因此最早只有127个字符被编码到计算机里也就是大小写英文字母、数字和一些符号这个编码表被称为ASCII编码比如大写字母A的编码是65小写字母z的编码是122。
但是要处理中文显然一个字节是不够的至少需要两个字节而且还不能和ASCII编码冲突所以中国制定了GB2312编码用来把中文编进去。
你可以想得到的是全世界有上百种语言日本把日文编到Shift_JIS里韩国把韩文编到Euc-kr里各国有各国的标准就会不可避免地出现冲突结果就是在多语言混合的文本中显示出来会有乱码。 因此Unicode应运而生。Unicode把所有语言都统一到一套编码里这样就不会再有乱码问题了。
Unicode标准也在不断发展但最常用的是用两个字节表示一个字符如果要用到非常偏僻的字符就需要4个字节。现代操作系统和大多数编程语言都直接支持Unicode。
现在捋一捋ASCII编码和Unicode编码的区别ASCII编码是1个字节而Unicode编码通常是2个字节。
字母A用ASCII编码是十进制的65二进制的01000001
字符0用ASCII编码是十进制的48二进制的00110000注意字符0和整数0是不同的
汉字中已经超出了ASCII编码的范围用Unicode编码是十进制的20013二进制的01001110 00101101。
你可以猜测如果把ASCII编码的A用Unicode编码只需要在前面补0就可以因此A的Unicode编码是00000000 01000001。
新的问题又出现了如果统一成Unicode编码乱码问题从此消失了。但是如果你写的文本基本上全部是英文的话用Unicode编码比ASCII编码需要多一倍的存储空间在存储和传输上就十分不划算。
所以本着节约的精神又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节常用的英文字母被编码成1个字节汉字通常是3个字节只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符用UTF-8编码就能节省空间
字符ASCIIUnicodeUTF-8A0100000100000000 0100000101000001中x01001110 0010110111100100 10111000 10101101
从上面的表格还可以发现UTF-8编码有一个额外的好处就是ASCII编码实际上可以被看成是UTF-8编码的一部分所以大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
搞清楚了ASCII、Unicode和UTF-8的关系我们就可以总结一下现在计算机系统通用的字符编码工作方式
在计算机内存中统一使用Unicode编码当需要保存到硬盘或者需要传输的时候就转换为UTF-8编码。
用记事本编辑的时候从文件读取的UTF-8字符被转换为Unicode字符到内存里编辑完成后保存的时候再把Unicode转换为UTF-8保存到文件 浏览网页的时候服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器 所以你看到很多网页的源码上会有类似meta charsetUTF-8 /的信息表示该网页正是用的UTF-8编码。
Python的字符串
搞清楚了令人头疼的字符编码问题后我们再来研究Python的字符串。
在最新的Python 3版本中字符串是以Unicode编码的也就是说Python的字符串支持多语言例如 print(包含中文的str)
包含中文的str对于单个字符的编码Python提供了ord()函数获取字符的整数表示chr()函数把编码转换为对应的字符 ord(A)
65ord(中)
20013chr(66)
Bchr(25991)
文如果知道字符的整数编码还可以用十六进制这么写str \u4e2d\u6587
中文两种写法完全是等价的。
由于Python的字符串类型是str在内存中以Unicode表示一个字符对应若干个字节。如果要在网络上传输或者保存到磁盘上就需要把str变为以字节为单位的bytes。
Python对bytes类型的数据用带b前缀的单引号或双引号表示
x bABC要注意区分ABC和bABC前者是str后者虽然内容显示得和前者一样但bytes的每个字符都只占用一个字节。
以Unicode表示的str通过encode()方法可以编码为指定的bytes例如 ABC.encode(ascii)
bABC中文.encode(utf-8)
b\xe4\xb8\xad\xe6\x96\x87中文.encode(ascii)
Traceback (most recent call last):File stdin, line 1, in module
UnicodeEncodeError: ascii codec cant encode characters in position 0-1: ordinal not in range(128)纯英文的str可以用ASCII编码为bytes内容是一样的含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码因为中文编码的范围超过了ASCII编码的范围Python会报错。
在bytes中无法显示为ASCII字符的字节用\x##显示。
反过来如果我们从网络或磁盘上读取了字节流那么读到的数据就是bytes。要把bytes变为str就需要用decode()方法 bABC.decode(ascii)
ABCb\xe4\xb8\xad\xe6\x96\x87.decode(utf-8)
中文如果bytes中包含无法解码的字节decode()方法会报错 b\xe4\xb8\xad\xff.decode(utf-8)
Traceback (most recent call last):...
UnicodeDecodeError: utf-8 codec cant decode byte 0xff in position 3: invalid start byte如果bytes中只有一小部分无效的字节可以传入errorsignore忽略错误的字节 b\xe4\xb8\xad\xff.decode(utf-8, errorsignore)
中要计算str包含多少个字符可以用len()函数 len(ABC)
3len(中文)
2len()函数计算的是str的字符数如果换成byteslen()函数就计算字节数 len(bABC)
3len(b\xe4\xb8\xad\xe6\x96\x87)
6len(中文.encode(utf-8))
6可见1个中文字符经过UTF-8编码后通常会占用3个字节而1个英文字符只占用1个字节。
在操作字符串时我们经常遇到str和bytes的互相转换。为了避免乱码问题应当始终坚持使用UTF-8编码对str和bytes进行转换。
由于Python源代码也是一个文本文件所以当你的源代码中包含中文的时候在保存源代码时就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时为了让它按UTF-8编码读取我们通常在文件开头写上这两行
#!/usr/bin/env python3
# -*- coding: utf-8 -*-第一行注释是为了告诉Linux/OS X系统这是一个Python可执行程序Windows系统会忽略这个注释
第二行注释是为了告诉Python解释器按照UTF-8编码读取源代码否则你在源代码中写的中文输出可能会有乱码。
申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的必须并且要确保文本编辑器正在使用UTF-8 without BOM编码 如果.py文件本身使用UTF-8编码并且也申明了# -*- coding: utf-8 -*-打开命令提示符测试就可以正常显示中文