Python学习笔记(7)Python编码

字符编码

ASCII:只能存英文和拉丁文符。一个字节(byte)8个比特(bit)。

gb2312: 6700多个中文,1980年。

GBK1.0: 20000多个字符,1995年。

 

Unicode把所有语言统一到一套编码里。

UTF-32:一个字字符占两个字节。

UTF-16:一个字符占两个字节或两个以上。

UTF-8:一个英文用ASCII码来存,一个中文占3个字节。

 

ASCII编码是1个字节,而Unicode编码通常是两个字节。

 

如果统一成Unicode编码,但英文会浪费许多空间,所以出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节。

 

 

Python3编码:

str:Unicode    bytes:十六进制

 

str >> bytes 编码 

编码的两种方式:

>>> s = 'hello, 王海宁'

>>> b1 = bytes(s, 'utf8')

>>> b1
b'hello, \xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'

>>> b2 = s.encode('utf8')
>>> b2
b'hello, \xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'

 

bytes >> str

解码两种方式

>>> b1
b'hello, \xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'

>>> s1 = str(b1, 'utf8')
>>> s1
'hello, 王海宁'

>>> s2 = b1.decode('utf8')
>>> s2
'hello, 王海宁'

 

注意:用UTF-8编码的字符不能用GBK解码,用GBK编码的字符也不能用UTF-8解码。

  >>> s = 'hello 王海宁'
  >>> s
  'hello 王海宁'
  >>> b1 = bytes(s, 'utf8')
  >>> b1
  b'hello \xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'
  >>> s1 = b1.decode('utf8')
  >>> s1
  'hello 王海宁'
  >>> s1 = b1.decode('gbk')
  Traceback (most recent call last):
  File "<pyshell#128>", line 1, in <module>
  s1 = b1.decode('gbk')
  UnicodeDecodeError: 'gbk' codec can't decode byte 0x81 in position 14: incomplete multibyte sequence

 

>>> 'hello'.encode('utf8')
b'hello'
>>> '王海宁'.encode('utf8')
b'\xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'

 

>>> 'hello'.encode('gbk')
b'hello'
>>> '王海宁'.encode('gbk')
b'\xcd\xf5\xba\xa3\xc4\xfe'

 

>>> 'hello'.encode('ascii')
b'hello'
>>> '王海宁'.encode('ascii')
Traceback (most recent call last):
File "<pyshell#113>", line 1, in <module>
'王海宁'.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

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

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

 

 

 

 

 

Python2特点:

python2默认编码为ASCII

python2中:

>>> import sys
>>> sys.getdefaultencoding()
'ascii'

Python 2.7.12 (default, Dec 4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> len('王海宁')
9
>>> len(u'王海宁')
3
>>> 'hello' + '王海宁'
'hello\xe7\x8e\x8b\xe6\xb5\xb7\xe5\xae\x81'

>>> u'hello' + 'world'
u'helloworld'

>>> u'hello' + '王海宁'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)

 

str和unicode都是basestring的子类,严格的意义上说,str其实是字节串,它是经过编码后的字节组成的序列。对UTF-8编码的str'苑'使用len()函数时,结果是3,因为utf8编码的'苑'是‘\xe8\x8b\x91’。而unicode是一个字符串,str是unicode这个字符串经过编码(utf8,gbk等)后的字节组成的序列。unicode才是真正意义上的字符串,对字节串str使用正确的字符编码进行解码后获得,并且len(u'苑') == 1。在py2里,str = bytes,Python2的最大的特点是Python2会自的将bytes数据解码成unicdoe字符串。

 

Python3特点:

python3默认Unicode

python3中:

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'

>>> len('王海宁')
3

Python3也有两种类型,一个是Unicode,一个是bytes码,但它们有不同的命名。

Python3对文本和二进制数据做了更清晰的区分。

文本总是Unicode由str类表示,二进制由bytes类型表示。Python3不会以任意隐式的方式混用str和bytes,正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串,也不能将字符串传入参数为字节包的函数。

 

计算机通用字符的编码方式:

在计算机内存中,统一使用Unicode编码,当需要保存硬盘或者需要传输时,就转化为UTF-8编码。

在用记事本编辑的时候。从文件读取的UTF-8字符串被转换为Unicode字符串到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。

 

len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数。

>>> len('hello')
5
>>> len(b'hello')
5

 

>>> len('王海宁')
3

>>> len('王海宁'.encode('utf8'))
9
>>> len('王海宁'.encode('gbk'))
6

 

注意

(1)在操作字符串时,我们经常遇到str和bytes的互相转换,为了避免乱码问题,应坚持使用UTF-8编码对str和bytes进行转换。

 

(2)声明的编码必须与文件实际保存时的编码一致。

由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:

#!/usr/bin/env python3

# -*- coding: utf-8 -*-   #为了告诉Python解释器,按照UTF-8编码读取源代码,否则,在源代码中写中文输出可能会有乱码。申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须确保文本编辑器正在使用UTF-8 without BOM编码。

 

posted on 2018-04-11 16:09  童话与海  阅读(195)  评论(0)    收藏  举报

导航