字符编码
我们人类使用字母和数字来进行交流,但是计算机只能识别数字,那么我们该如何将字母和数字转换为对应能让计算机读懂的数字呢?于是字符编码应运而生。
由于计算机最早出现在美国,美国就编定了以英语为基础的对应字符编码格式,也就是ASCII
编码,这个编码规定一个字节(byte)由8个bit组成,而2^8=256,所以ASCII
编码能够容纳255个位置,其中包含了英语大小写,数字及常用的各种符号。并且由此规定了第一个字符编码规则
但是随着计算机的传播,英语不能满足各个国家交流运用的需求,很显然区区255个空位完全不足以容纳汉字数量,于是中国效法ASCII编码表创立了GB2312
编码表,使用两个字节(byte)来容纳汉字。同样地,日本创立了Shift_JIS
编码表,韩国创立了Euc-kr
编码表......但很显然,这样子很容易出现撞车的情况,所以在多语言混合运用文本中会经常出现乱码的情况
随后,Unicode
编码表被规定,解决了乱码问题,因为它把所有的文字编定到了一个编码表之中。在Unicode
中规定,两个字节(部分极其偏僻字符除外)表示一个字符
例如:
字母A用ASCII编码是十进制的65,二进制的01000001;
字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的;
汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101
同理,在字母A中如果要转换成Unicode编码,只需要在其ASCII编码前补全0即可,因此字母A的Unicode编码是00000000 01000001
但是新的问题出现了:太!浪!费!了!
要知道,现在固态硬盘的价格已经到了1元/G啊啊啊!
如果我们仅仅存储英文字符,那么会有大量空间被不必要的00000000来占用,因此后来科学家们又规定了一种新的“可变长编码”——UTF-8
,它把一个Unicode字符根据数字大小分为1-6个字节,其中英语使用1个字节来表示,汉字使用3个字节来表示,更长的字节往往表示一些非常罕见的字符
字符 | ASCII | Unicode | UTF-8 |
---|---|---|---|
A | 01000001 | 00000000 01000001 | 01000001 |
中 | / | 01001110 00101101 | 11100100 10111000 10101101 |
同时通过对比我们还可以发现,ASCII编码被包含于UTF-8之中,所以很多之前的ASCII程序也可以正常运行了
所以在计算机运行过程中,计算机的运算环节在Unicode编码下运行,而存储环节在UTF-8编码下存储。而当我们访问网页时,服务器会把动态生成的Unicode编码转换成UTF-8编码再传送到浏览器
字符串
在python3中,字符串以Unicode进行编码,因此我们可以在python中输出多种语言
同时,我们可以通过ord()
函数来获取字符的整数表示编码,而我们可以使用chr()
函数来讲整数的编码转换为字符
在知道字符的整数编码后,我们可以反过来通过其十六进制的形式来直接表示字符
在python中,字符以Unicode的格式加载在内存中,以UTF-8
格式存储在硬盘上和在网络上传输。
所以在python中,对bytes
类型的数据以带b为开头的单双引号构成:b'ABC'
,值得注意的是,ABC
与b'ABC'
尽管在显示时内容一样,但是实际上前者每个字符占用两个字符,后者每个字符只占用一个bytes
以Unicode编码的内容可以通过encode()
函数来讲内容编码为指定的bytes
相反,我们可以通过decode()
函数来将接收到的字符串转换为相关字符
在bytes
中,无法显示为ASCII字符的字节,用\x##
显示,而当遇到少量的无法显示字节时我们可以传入errors='ignore'
忽略错误的字节
我们可以使用len()
函数来计算字节数
在操作字符串相关时,我们经常会涉及到str和bytes的相互转换,为了避免出现乱码问题,我们应该始终使用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编码。
格式化
在输出中,我们还常常会遇到一个问题:如果我们需要输出“今天是xxxx年xx月xx天”这种因时而变的内容,我们该怎么做?
这便是格式化的作用了。在python中,我们与C语言一样使用%
符号来实现格式化
一般地,我们使用%
符号来表示格式化字符串,使用%s
来表示用字符串替换,使用%d
来表示用整数替换,使用%?
表示替换,有几个%?
占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?
,括号可以省略。
常见的占位符有:
占位符 | 替换内容 |
---|---|
%d | 整数 |
%f | 浮点数 |
%s | 字符串 |
%x | 十六进制整数 |
感觉好多?有个简单的方法:如果你知不道该用哪个,那么就一个个用%s
对应下去即可
如果我们就是想要写出%
这个字符怎么办?我们就需要连着输入%%
进行标识
我们还有另一种用以表示格式化的方法,即使用format()
函数,他会使用传入的参数依次填入占位符中的{1},{2}......
除此之外我们还有一种表示格式化的方法,即使用以f
开头的字符串,我们称之为f-string
,在f-string
中,如果字符串中包含{xxx},那么将会以xxx的变量进行替换