Python字符编码
字符初期
(1)计算机只能处理数字,如果处理文本,需要把文本转换为数字
才能处理.最早的计算机在设计时采用8个比特(bit)
作为一个字节(byte)
,所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255)
,如果需要表示更大的整数,需要更多的字节,比如2个字节可以表示最大整数65535
,4个字节最大整数4294967295
一个字节8个比特(bit)!2个字节就是16比特,4个字节就是32字节!
0~65535=65536(2^16-1+1) >>(计算机从0开始计算,0也算一个存储单位,所以要加上)
ASCII编码
(2)由于计算机是美国发明的,因此最早只有127个
字符被编码到计算机中,也就是大小写英文字母,数字和一些符号,这个编码表被称为**ASCII
**编码,比如大写字母Z
的编码是90
,小写字母a
的编码是97
.
GB2312编码
(3)处理中文显然一个字节是不够的,值少需要两个字节,还不能和ASCII
编码冲突,所以中国制定GB2312
编码,
(4)全世界有几百种语言,比如:
日本编码
Shift_JIS
每个国家都有自己的标准,就不可避免的出现冲突,结果就是现实乱码!
乱码后
Unicode编码
(5)字符编码Unicode
出世了,Unicode
把所有语言都统一到一个套编码
里,这样不在有乱码问题了!!
Unicode也在不断的发展,但最常用的就是2个字节表示一个字符
(如果非常偏僻
的字符,需要4个字节
),现代操作系统和大多数编程语言都直接支持Unicode.
ASCII/Unicode的区别?
ASCII
ASCII编码是
1个字节
Unicode
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存储空间多一倍!在
存储
和传输
上很不划算!
UTF-8编码
为节约存储和传输上的不划算,出现了把Unicode编码转化为"可变长编码"
的**UTF-8
**编码,把一个Unicode字符根据不同的数字大小编程1-6
个字节,常用的英文
编码成1个字节
.汉字
一般是3个字节
,只有很生僻
的字符才编码为4-6个字节
,现在如果你文本中含有大量英文字符,用UTF-8
会节省很多空间.
在上图可以发现,UTF-8的一个额外好处,就是ASCII编码实际可以被看成UTF-8的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8下继续工作!
小结
计算机系统通用的字符编码工作方式:
1)在计算机内存中,统一使用Unicode编码
,当需要保存到硬盘或者传输的时候,转换为UTF-8编码
2)用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候在把Unicode转换为UTF-8保存到文件
3)浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器
所以在看网页源码的时候会有类似<meta charset="UTF-8" />
的信息,表示网页用的是UTF-8编码.
Python的字符串
(1)在python3版本中,字符串是以Unicode编码的,python支持多语言,如
>>>print("shuai的帅")
shuai的帅
(2)对于单个字符的编码,python还提供了两个函数:
**ord()函数
**获取字符的整数表示;
**chr()函数
**把编码转换为对应的字符;
>>> ord('S')
83
>>> ord('帅')
24069
>>> chr(24069)
'帅'
>>> chr(83)
'S'
(3)如果知道字符的整数编码,还可以用十六进制写str
:
解释说明:
str=string >>字符类型(字符串)
>>>"\u4e2d\u6587"
'中文'
(4)由于python的字符类型时str
内存中以Unicode表示,一个字符对应多个字节,如果需要在网络传输,或保存到磁盘上,就需要把str
变为以字节为单位的bytes
name = b"shuai"
要注意区分shuai
和b"shuai"
,前者是str
,后者虽然内容显示的和前者一样,但是bytes
的每个字符都只占用一个字节
.
以3Unicode表示的str
通过encode()方法
可以编码为指定的bytes
,例如:
>>>'zhang'.encode('ascii')
b'zhang'
>>>'张'.encode('utf-8')
b'\xe5\xbc\xa0'
>>>'张'.encode('ascii')
---------------------------------------------------------------------------
#报错:
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-20-e1fb28eb976f> in <module>
----> 1 '张'.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character '\u5f20' in position 0: ordinal not in range(128)
说明
纯英文的
str
可以使用ASCII
编码为bytes
,内容是一样的,含有中文的str
可以用UTF-8编码为bytes
,还有中文的str
无法用ASCII
编码,因为中文编码范围超过了ASCII
编码的范围,python会像上面例子一样报错
(5)在bytes
中,如果我们从网络或磁盘上读取了字节流,那么读取到的数据就是bytes
,要把bytes
变为str
,就要使用**decode()方法
**
>>>b'shuai'.decode('ascii')
'shuai'
>>>b'\xe5\xbc\xa0'.decode('utf-8')
'张'
如果bytes
中包含无法解码的字节, **decode()方法
**会报错
>>>b'\xe5\xbcs\xa0'.decode('utf-8')
---------------------------------------------------------------------------
#报错
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-24-9f762c468f58> in <module>
----> 1 b'\xe5\xbcs\xa0'.decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 0-1: invalid continuation byte
(6)如果bytes
中只有一小部分无效字节,可以传入errors='ignore'
忽略报错字节
>>>'大神'.encode('utf-8') #正常
b'\xe5\xa4\xa7\xe7\xa5\x9e' #正常输出
>>>b'\xe5\xa4\xa7\xe7\x2a282\x922edd'.decode('utf-8',errors='ignore') #使用errors='ignore',并改错编码
'大*2822edd' #有效字节继续输出
>>>b'\xe5\xa4\xa7\xe7\xasssss5\x9e'.decode('utf-8') #不加errors='ignore'
---------------------------------------------------------------------------
#报错
File "<ipython-input-32-362b4cfd219c>", line 1
b'\xe5\xa4\xa7\xe7\xasssss5\x9e'.decode('utf-8')
^
SyntaxError: (value error) invalid \x escape at position 16
(7)要计算str
包含多少个字节,可以使用**len()函数
**
>>>len('shuai')
5
>>>len('帅')
1
**len()函数
**计算的是str
的字符数,如果换成bytes
,len()
函数就计算字节数:
>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6
说明
一个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用一个字节.
在操作字符串时,经常遇到str
和bytes
的相互转换,为了避免乱码问题,应当始终坚持使用UTF-8
编码对str
和bytes
进行转换.
(8)如何让python自动保存为UTF-8编码呢
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
说明
第一行告诉系统这是一个python可执行程序
第二行告诉python解释器使用UTF-8编码读取源代码
即便声明了,也要在使用编辑器的时候,把编辑器的编码格式改为相对应的字符集!
格式化
(1)什么是格式化输出?
有时会输出如以下:
**你好XXX,我是XXX公司的我叫XXXX,
**这里面的XXX就是要根据变量
的变化而变化,需要一种简便的格式化字符串的方式来搞定!
(2)在python中采用的格式化方式是**%
**来实现的.
>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
%
运算符就是用来格式化字符串的,在字符串内部,%s
表示用字符串代替,%d
表示用整数代替,有几个%?
,后面就更几个比变量或者值,顺序要对应好,如果只有一个%?
,括号可以省略
占位符 | 替换内容 |
---|---|
%d | 整数 |
%f | 浮点数 |
%s | 字符串 |
%x | 十六进制整数 |
格式化整数和浮点数还可以指定是否补0和整数与小数的位数
以下是指定整数和小数的位数
以下是指定是否补0
说明
如果你不知道自己该用什么,那么就使用万能的**
%s
**,它会把任何数据类型转换成字符串
>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'
(3)format()方法
format()方法
它会用传入的参数依次替换字符串的占位符{0}
,{1}
,{2}
…,不过这种范式写起来要比%
麻烦~
>>> 'Hi, {0}, 成绩提升了 {1:.1f}%'.format('小黑', 13.12225)
'Hi, 小黑, 成绩提升了 13.1%'