《Fluent Python》读书笔记-Text versus Bytes

概览

    "string"的概念很简单,就是字符的序列。但是怎么定义字符是一个问题。在python3,str是由Unicode字符组成,而在python2里str是由原始的byte字符组成。
    Unicode标准把字符的标识和字符的二进制表示区分开来:

  • 字符的标识,即码位(code point),是一个从0到1,114,111的数字,在Unicode标准里是以U+为前缀的4到6位的16进制数字。如字母A的码位是U+0041。
  • 实际的一个字符的二进制表示是由具体使用的编码(encoding)决定。如字母A在UTF-8编码里是单个字节\x41而在UTF-16LE编码下是两个字节\x41\x00。
        从码位转换字节是encoding,从字节转换到码位是decoding。

字符编码的各式各样的问题

    本章后面讲了很多因为字符编码产生的问题,在目前做过的项目中基本没碰到过,感觉主要出现在像希腊语,葡萄牙语还有泰米尔语这类语言上,也没去深入研究,简单做下总结。

  • 有些编码包含的字符只是Unicode的一个子集,当把一个Unicode字符转换到目标编码时,如果目标编码不包含这个字符的定义,则会报UnicodeEncodeError,可以通过在encode方法中加入error参数,对错误进行忽略或者做一些处理。
  • 如果二进制编码有错,不是一个有效的编码,则在把二进制编码转换到Unicode字符时,会报UnicodeDecodeError,也可以通过在decode方法中加入error参数,对错误进行忽略或者做一些处理。
  • 从python3开始,源码的默认编码采用UTF-8,而python2的默认编码是ASCII,意味着#!coding: utf8不需要再加了。
  • 作者讨论了下是不是能从二进制序列里发现编码方式,答案是不可以。但是可以通过一些特殊的规则大概确定一下,作者介绍了个chardet的项目。
  • BOM是用来标识大端序和小端序的,对于UTF-16是需要的,但是对于UTF-8不是必须的,python没有使用BOM来判断一个文件是否是UTF-8。
  • 如果使用python默认的编码,可能会出问题,比如用UTF-8编码写一个文件,但是读的时候没指定编码,在Linux上没问题,但是可能在Windows上就有问题。最好是在所有的操作上都明确指定编码格式。
  • 因为组合字符的原因,字符串比较会有些问题,打印出来是一样的字符,可能实际的编码不一样,python提供了一些normalize方法进行归一化,不过作者也提到像google就是直接把这些变音符给去掉。
  • 在字符串排序时有可能也会出现问题,作者推荐了个PyUCA。
  • python中有一个完整的Unicode database,记录了每个字符的各方面的信息。
  • python的接口可以支持str和bytes的输入参数,但是根据参数类型不同,结果也不同。
  • python提供了struct模块去对打包在一起的bytes进行拆包。
>>> import struct
>>> fmt = '<3s3sHH' #
>>> with open('filter.gif', 'rb') as fp: ... img = memoryview(fp.read()) # ...
>>> header = img[:10] #
>>> bytes(header) # b'GIF89a+\x02\xe6\x00'
>>> struct.unpack(fmt, header) # (b'GIF', b'89a', 555, 230)
>>> del header #
>>> del img

你可能感兴趣的:(《Fluent Python》读书笔记-Text versus Bytes)