Python编程:文本和字节序列

1.字符问题 

        “字符串”是一个相对简单的概念,一个字符串代表一个字符序列。但是问题出在“字符”的定义上。在Unicode标准中,对字符地标识和字节的具体表述进行了详细的划分。

       字符的标识,即码位,是0-1114111的数字(十进制),在Unicode标准中码位以4-6个十六进制数字表示,而且要加上前缀“U+”。例如,A的码位为U+0041。

       字符的具体表述则取决于所用的编码。编码是在码位和字节序列之间转换时所用到的算法。例如,在UTF-8编码中,A(U+0041)码位编码成单个字节\x41。

       综上,将码位转换成字节序列的过程称为编码,将字节序列转换成码位的过程称之为解码。编码(.encode())是将人类可读的文本转换成机器可读的字符序列。解码(.decode())是将机器可读的字符序列转换成人类可读的文本。

s = 'cafe'
b = s.encode('utf8')
print(b)
c = b.decode('utf8')
print(c)

2.字节概要

       bytes和bytearray对象的各元素是介于0-255之间(也就是range(0,256))的整数,但是二进制序列的切片始终是同一类型的二进制序列,包括长度为1的切片,只不过该序列中存放的元素还是整数。

cafe = bytes('cafe', encoding='utf8')
print(cafe)
print(cafe[0])
print(cafe[:1])

        构建bytes和bytearray实例可以还可以调用各自的构造方法。一般传入下述的参数就可:

(1)一个str对象,一个encoding关键字参数,就是采用的编码算法。

(2)一个可迭代的对象,提供0-255之间的一个整数。

(3)一个实现了缓冲协议的对象(如bytes、bytearray),此时,会把源对象序列中的字节序列复制到新的二进制序列中。

import array
numbers = array.array('h', [-2,-1,0,1,2])
octets = bytes(numbers)
print(octets)

        使用缓冲类对象创建bytes和bytearray对象时,始终复制的是源对象中的字节序列。与之相反的是,memoryview对象允许在二进制数据结构之间共享内存。

3.结构体和内存视图

        struct模块提够了一些函数,把打包的序列转换成不同类型字段组成的元组,以及一些反向转换的函数。struct模块能够处理bytes、bytearray和memoryview等对象。

import struct
# 其中<代表小字节序,3s3s代表两个三字节序列,HH代表两个16位二进制整数
fmt = '<3s3sHH'
with open('filter.gif', 'rb') as fp:
    img = memoryview(fp.read())
# 使用切片在创建一个对象
header = img[:10]
# 转换为字节序列
a = bytes(header)
# 以fmt构建的形式对header进行拆包
b = struct.unpack(fmt, header)
#删除引用释放内存
del header
del img

4.处理文本文件

       处理文本的最佳实践是“Unicode三明治”,即要尽早把输入的字节序列解码成字符串,尽量晚的把字符串编码成字节序列。在处理文本文件时,要注意,一定不要依赖默认编码,打开文件时,始终应该明确地传入encoding=参数,因为系统不一样默认的编码方法也是不一样的,这会导致一些兼容性问题。

       在Python中,locale.getpreferredencoding()返回的编码是最重要的,它是打开文件的默认编码,也是重定向文件的默认编码。但是在不同的系统中设置起来会比较麻烦,所以,最好的建议是别依赖默认值。

5.为了正确比较而规范化Uniccode字符串

        因为Unicode有组合字符,所以字符串比较起来会比较麻烦。因为同一个词会有多种表示方法。为了解决这个问题,我们一般使用unicodedata.normalize()函数提供的规Unicode规范化。该函数的第一个参数有四种,即:NFC(推荐使用),NFD,KNFC,KNFD。NFC参数表示是用最少的码位构成等价的字符串。NFD把组合字符分解成基字符和单独的组合字符。KNFC和KNFD为更严格的规范化形式,一般不使用。

from unicodedata import normalize

s1 = 'cafe\u0301'
s2 = 'café'
print(len(normalize('NFC', s1)), len(normalize('NFC', s2)))
print(s1, s2)
print(len(s1), len(s2))
print(s1 == s2)

       此外,规范化时,还要注意将大小写进行折叠,就是把所有文本都变成小写,再做一些其它转变。这个功能由str.casefold()来实现。

6.Unicode文本排序

        一般来说,我们使用PyUCA库来实现排序算法。但是它没有考虑区域设置,如果想定制排序方式,可以把自定义的排序表路径传给collator构造方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值