Python编码

编码

  • 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。
  • 用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件
  • 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器
  • 1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> ord('A')
    65
    >>> ord('中')
    20013
    >>> chr(66)
    'B'
    >>> chr(25991)
    '文'
    >>> '\u4e2d\u6587'
    '中文'

str和bytes

1
2
x=b'ABC'
y='ABC'

y是str,x是bytes,内容显示一样,但bytes每个字符都只占用一个字节

  • Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes(各个平台的编码不一定都相同,socket 传递的数据都是bytes类型的,避免乱码)
  • Python 3 不会以任意隐式的方式混用strbytes
  • Bytes 对象是由单个字节作为基本元素(8 位,取值范围 0-255)组成的序列,为不可变对象。
  • Bytes对象只负责以二进制字节序列的形式记录所需记录的对象,至于该对象到底表示什么(比如到底是什么字符)则由相应的编码格式解码所决定。我们可以通过调用bytes() 类(没错,它是类,不是函数)生成bytes实例,其值形式为b'xxxxx',其中'xxxxx'为一至多个转义的十六进制字符串(单个 x 的形式为:\xHH,其中 \x 为小写的十六进制转义字符,HH 为二位十六进制数)组成的序列,每个十六进制数代表一个字节(八位二进制数,取值范围 0-255),对于同一个字符串如果采用不同的编码方式生成 bytes 对象,就会形成不同的值

str编码为指定的bytes

1
2
3
4
5
6
7
8
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。

bytes中,无法显示为ASCII字符的字节,用\x##显示。

bytes编码为str

1
2
3
4
5
6
7
8
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf8')
'中文'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

len函数

1
2
3
4
5
6
7
8
>>> len('ABC')
3
>>> len('中文')
2
>>> len(b'abc')
3
>>> len('中文'.encode('utf8'))
6

文件编码

1
2
#!/usr/bin/env python
# encoding=utf-8

第一行会告诉系统使用的python路径,不建议使用#!/usr/bin/python,灵活性降低

1
2
3
4
import sys
sys.getdefaultencoding()
'utf-8'

格式化

1
2
3
4
5
6
7
8
9
10
11
>>> 'Hello,%s'%'world'
'Hello,world'
>>> 'Hi,%s,you have $%d.'%('Michael',10000)
'Hi,Michael,you have $10000.'
>>> print('$%2d-$%02d' % (3,1))
$ 3-$01
>>> print('%.2f' % 3.1415926)
3.14
>>> 'growth rate:%d %%' % 7
'growth rate:7 %'

%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数

如果不太确定应该用什么,%s永远起作用

format()

1
2
>>> 'Hello,{0},成绩提升了{1:.1f}'.format('小明',17.125)
'Hello,小明,成绩提升了17.1'

参考: