Unicode 简介

字符 character

编码点 code point:字符在字符集中的序号,非负整数

字形 glyph:字符的显示形式,跟渲染方式有关

编码 encoding:字符在内存中的二进制表示形式,由一个或多个编码单元 code units 组成

编码单元 code units:对应一个或多个字节

中文汉字范围,即中日韩统一表意文字编码范围为U+4E00–U+9FFF。

Python的Unicode支持

String 类

支持使用ASCII和转义字符表示Unicode字符

"\N{GREEK CAPITAL LETTER DELTA}" 

上述代码打印出希腊字母delta(根据系统不同,可能打印出’\u0394’) 编码点和字符的转换:chr()ord()能够完成单字符和编码点(整数)间的转换。例如:

>>> ord('中')  # 求汉字'中'的编码点
20013
>>> chr(20013)  # 将编码点转换为字符
'中'
>>> hex(ord('中'))  # 以十六进制形式表示
'0x4e2d'
>>> chr(0x4e2d)  # 将编码点转换为字符
'中'
>>> '\u4e2d'  # 字符'中'的编码点书写形式
'中'

转换成Bytes

bytes.decode()str.encode()完成strbytes类型之间的转换。

源码中的Unicode 字面量

字符既可以用字面形式书写,如:’a’,也可以用编码点形式书写,如:’\x61’。对于不可打印字符,只能用编码点形式书写。

Unicode字面量书写形式:

  • \x,后面跟2个16进制整数,表示1个Unicode字符
  • \u,后面跟4个16进制整数
  • \U,后面跟8个16进制整数
'\x61'
'\u0061'
'\U00000061'
'a'

上述均表示字符’a’。

源码默认UTF-8编码,可通过注释显示声明。

#!/usr/bin/env python
# -*- coding: latin-1 -*-
u = 'abcdé'
print(ord(u[-1]))

-*-表示该注释是特殊的(Emacs风格),coding=name亦可。

读写Unicode数据

open()error参数可以设置编码错误的处理方法。

编写支持Unicode程序的建议

Software should only work with Unicode strings internally, decoding the input data as soon as possible and encoding the output only at the end.

文件编码转换

StreamRecoder类能够转换数据流的编码

new_f = codecs.StreamRecoder(f,
    # en/decoder: used by read() to encode its results and
    # by write() to decode its input.
    codecs.getencoder('utf-8'), codecs.getdecoder('utf-8'),
    # reader/writer: used to read and write to the stream.
    codecs.getreader('latin-1'), codecs.getwriter('latin-1') )

上述代码,数据写入时,通过decoder按照UTF-8解码成中间形式,然后按照latin-1编码,写到下游;

数据读取时,通过reader按照latin-1解码成中间形式,然后按照UTF-8编码,返回。

未知编码的文件

使用errors参数,指定相应的编码错误处理器。


with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

# make changes to the string 'data'

with open(fname + '.new', 'w',
          encoding="ascii", errors="surrogateescape") as f:
    f.write(data)

上述代码只修改ASCII字符,其他字符保持原样。

str和bytes类

简单将str 对象理解为unicode字符的码点序列,每个元素对应一个字符,对应的二进制值是码点(ordinal);

bytes 对象理解为编码后的字节序列,每个元素是一个0-255的整数,1个或多个元素对应一个字符,且二进制值和编码方式有关,不能直接对应unicode码点。

str

Strings are immutable sequences of Unicode code points.

str类是不可变的Unicode编码点的序列。 str.encode 方法将str对象转换成bytes对象。

bytes

Bytes objects are immutable sequences of single bytes.

bytes类是不可变的字节序列。

bytes类是内置类型,bytes对象的创建,可以通过:

  • 直接字面量创建:b' Only ASCII character are permmitted in bytes literals' ,只有ascii字符可以直接写成bytes字面量,超过127的要用转义字符,b’\xe4\xbd\xa0’
  • 使用十六进制数字创建,空格被忽略:
>>> bytes.fromhex('2Ef0 F1f2  ')
# 2E是'.'的ascii编码,直接以'.'显示
b'.\xf0\xf1\xf2'

bytes.decode 方法将bytes对象转换成str对象。

每个元素都是整数 int:

# print 49~53
for i in b'12345':
    print(i)

a = b'1'
print(type(a[0]))  # print int

bytearray

bytearray 对象相当于可变的 bytes 对象。

class bytearray([_source_[, _encoding_[, _errors_]]])

通过构造函数创建bytearray对象:

  • 空实例:bytearray()
  • 可以指定容量:bytearray(10)
  • 从列表或可迭代对象创建:bytearray(range(20))
  • 从bytes对象复制:bytearray(b'Hi')

bytes/bytearray除了可变性差异外,几乎可以认为等同。

类型转换

str bytes int
str str.encode int()
bytes bytes.decode int.from_bytes
int str() int.to_bytes

更多类型转换可以使用struct 模块。


<
Previous Post
String Formatting Best Practices
>
Next Post
import、module和package