流畅的Python
第四章总结
- 字符问题
Python3的str对象中获取的元素是Unicode字符。
Unicode标准:
码位:是0~1114111的数字(十进制),在Unicode标准中以4 ~ 6个十六进制的数字表示,且加前缀“U+”。
字节序列:从字节序列(非字符序列)到码位的过程是解码,从码位到字节序列的过程是编码。
>>> s = 'caf$'
>>> len(s)
4
>>> b = s.encode('utf8')
>>> b
b'caf$' #bytes类型以b开头
>>>
>>> b.decode('utf8')
'caf$'
- 字节概要
python3引入了不可变bytes类型和bytearray类型。两个类型的对象的各个元素都是位于0 ~ 255的整数。
>>> cafe = bytes('cafè',encoding = 'utf_8')
>>> cafe
b'caf\xc3\xa8'
>>> cafe[0]
99
>>> cafe[:1]
b'c'
>>> cafe_arr = bytearray(cafe)
>>> cafe_arr
bytearray(b'caf\xc3\xa8')
>>> cafe_arr[-1:]
bytearray(b'\xa8')
只有在str中s[0] == s[:1] 是对的,在其余的序列中s[0]返回的是一个元素,s[:1]返回的是一个只有一个元素的序列。
二进制序列会以三种方法显示:
- 可打印的ASCII范围内的字节(从空格到~),使用ASCII字符本身。
- 制表符,换行符,回车符和 \ 对应的字节,使用转义序列 \t,\n,\r,和 \\。
- 其他字节的值,使用十六进制转义序列。
二进制序列有个类方法,fromhex()。作用是解析十六进制数字,构建二进制序列:
>>> bytes.fromhex('314bcea9')
b'1K\xce\xa9'
使用数组中的原始数据初始化bytes对象:
>>> import array
>>> nums = array.array('h',[-2, -1, 0, 1, 2])
>>> octets = bytes(nums)
>>> octets
b'\xfe\xff\xff\xff\x00\x00\x01\x00\x02\x00'
- 处理编码错误
UnicodeDecodeError错误:
>>> octets = b'Montr\xe9al'
>>> octets.decode('cp1252')
'Montréal'
>>> octets.decode('iso8859_7')
'Montrιal'
>>> octets.decode('koi8_r')
'MontrИal'
>>> octets.decode('utf8')
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
octets.decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
>>> octets.decode('utf8', errors = 'replace')
'Montr�al'
UnicodeEncodeError错误:
与decodeError错误类似,当无法将一个字符解码成二进制序列时,会报错,可以使用encode(‘cp437’, errors = ‘ignore’),encode(‘cp437’, errors = ‘replace’),encode(‘cp437’, errors = ‘xmlcharrefreplace’)分别对错误进行跳过,替换成‘?’和替换成XML实体。
Python3默认使用UTF-8编码源码,如果打开包含UTF-8之外的数据,会抛出SyntaxError错误,这时可以在顶部添加注释:
# coding:cp1252
- BOM字节序标记
b’\xff\xfe 指明编码时使用小字节序,小字节序是指各个码位的最低有效字节在前面,例如字母’E‘的码位为U+0045(十进制69),则在字节偏移的第二位和第三位编码为69和0,大字节序则为0和69。
utf-16有两个变种:utf-16LE显式使用小字节序,utf-16BE显式使用大字节序。这两个不会生成BOM。
- 处理文本文件
使用read()和write()函数会自动将文本中的字节序列解码成字符串。
eval()函数,接受一个字符串参数,作用是将这个字符串当作python表达式执行,就相当于在python中写出这个字符串然后执行。
- 规范化Unicode字符串
Unicode有组合字符(字母加符号)如é可以看作e\u0301,因为码位序列不同,所以python判定这两个不相等,可以使用unicodedata.normalize将Unicode规范化,normalize()函数有两个参数,第一个是’NFC‘,’NFD‘,’NFKC‘,’NFKD‘四个中的一个,NFC指明使用最少的码位构成字符串,NFD则是将组合字符分解成基字符和单独的组合字符,NFKC和NFKD会将字符转化为兼容其他编码的字符,有时会改变意思,第二个参数即字符串。
casefold()函数与lower()函数得到的结果一样,只有少数的不一样,可忽略。