参考:字符串和编码
Note
A.字符编码
1.计算机处理文本 == 将文本转换为二进制 => 处理
2.8 bit(比特) = 1 byte(字节)
一个字节所能表示的最大的十进制整数是255,也就是二进制的11111111;两个字节 => 65535;四个字节 => 4294967295。
3.编码标准
美国的编码表 => ASCII编码表;中国的编码表(用两个字节表示汉字) => GB2312。
问题:各国有各国的编码,有如此多的编码,就会出现冲突,在多语言混合的文本中,会显示乱码。
解决方法:诞生Unicode。
Unicode vs ASCII:a.Unicode使用两个字节,ASCII使用一个字节。b.ASCII转Unicode,在前面补0.
eg.字符A:ASCII编码 => 01000001;Unicode编码:00000000 01000001。
Unicode的问题:
如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。
解决方法:使用“可变长编码”UTF-8编码。
UTF-8:根据字符大小编码成1~6个字节 => 英文字母1个;中文3个。
eg.
字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
中 x 01001110 00101101 11100100 10111000 10101101
UTF-8编码的好处:遗留的使用ASCII编码的软件可以在UTF-8下继续工作。
4.计算机系统的字符编码工作:
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
内存 => Unicode; 传输 => UTF-8
B.Python的字符串
1.在Python3版本中,使用的是Unicode编码,也就是说它支持多语言。
>>> print('你好')
你好
2.对于单个字符,Python提供了两个函数:a.ord()函数,得到字符的整数表示;b.chr()函数,把编码转换为对应的字符。
ord():
>>> ord('我')
25105
>>> ord('a')
97
chr():
>>> chr(29233)
'爱'
>>> chr(97)
'a'
3.Python的字符串类型是str => 内存中使用Unicode表示 => 一个字符对应多个字节;如果要传输 => 字符以字节byte为单位 => 一个字符对应一个字节。
x = b'ABC'
注意区分'ABC'和b'ABC':'ABC'是str,使用的是Unicode编码;而b'ABC'进行了转换,一个字符对应一个字节(如果字符对应有多个字节,则不能使用ASCII编码,见下一点)。
其实意思就是,对文本进行编码,编码前的字符串是'str',编码后的字符串则是b'str',以字节封装。
4.用Unicode表示的str通过encode()方法可以编码为指定的bytes,编码方式不含Unicode:
>>> 'ABC'.encode('ascii')
b'ABC'
>>> 'ABC'.encode('utf-8')
b'ABC'
>>> '我爱你'.encode('utf-8')
b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
>>> '我爱你'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
可以看到,中文是不能用ASCII编码方法进行编码的。
>>> x = b'我爱你'
File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
可以看到,使用语句x = b'[str]'
,默认将[str]转换为ASCII编码的字符串,再赋值给x。
5.有编码,也就有解码,Python提供decode()方法将编码(以byte为单位)转换为Unicode字符串(以bit为单位):
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'我爱你'.decode('ascii')
File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
>>> b'iloveyou'.decode('ascii')
'iloveyou'
>>> '我爱你'.encode('utf-8')
b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'
>>> b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'.decode()
'我爱你'
6.Python提供了计算字符串str长度的函数len(),当是bstr时,计算的就是字节数。
>>> len('ABC')
3
>>> len(b'ABC')
3
>>> len('我爱你')
3
>>> len(b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0'.decode('utf-8')) //对bytes字符串进行解码
3
>>> len('我爱你'.encode('utf-8')) //对字符串“我爱你”进行编码、编码方式utf-8.
9
>>> len(b'\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0')
9
可见,1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。
总结:为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。
Hint:
在Python脚本的前面,一般加上这两句话:
#!/usr/bin/env python3 //使计算机识别出这是一个Python的可执行文件
# -*- coding: utf-8 -*- //告诉Python解释器,按照UTF-8编码读取源代码
同时也要确保你的文本编辑器使用UTF-8编码方式。
格式化
Python使用%来格式化字符串,这一点和C语言一致。
常见的占位符有:
%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数
eg.
#!/usr/bin/env python3
print('Hi, My name is %s' % 'Chen') # Hint: no ","
print('Ethernet Type: %x, My QQ number: %s' % (0x0800, '952693358'))
print('My Student Number: %d' % 15)
sh-3.2# ./basic1.py
Hi, My name is %s Chen
Ethernet Type: %x, My QQ number: %s (2048, '952693358')
My Student Number: %d 15
sh-3.2# ./basic1.py
Hi, My name is Chen
Ethernet Type: 800, My QQ number: 952693358
My Student Number: 15
注意点:a.在%号前面没有“,”! b.如果字符串中出现%,使用两个%进行转移,即“%%”。
小数点后两位:
print('%.2f' % 3.1415926535)
确定位数,不足补0或空格:
print('%02d' % 1)
输出:
>>> 01
print('2d' % 1)
输出:
>>> [空格]1
作业
小明的成绩从去年的72分提升到了今年的85分,请计算小明成绩提升的百分点,并用字符串格式化显示出'xx.x%',只保留小数点后1位:
#!/usr/bin/env python3
s1 = 72
s2 = 85
r = s2
print('%.1f%%' % r)
2017/1/23