Python—编解码

编码发展史

计算机只能数字,无法处理文本,要处理文本必须先转为数字,早期计算机设计采用8比特(bit)为1个字节(byte),一个字节能表示的最大整数为255

ASCII编码

(American Standard Code for Information Interchange,美国信息互换标准代码),最早期只有127个字符被编码到计算机(大小写英文字母、数字和一些符号,比如:大写字母A的编码是65,小写字母z的编码是122)

GB2312编码

GB2312(中国国家标准简体中文字符集),中文的出现,ASCII的127个字符显然不能满足要求,处理中文至少需要两个字节,且不能和ASCII冲突,因此中国制定了GB2312用来把中文编进来

GBK编码

别名(cp936),后来发现GB2312还是不够用,于是进行扩展,产生了GBK(即汉字内码扩展规范)

GB13080编码

后来,为了容纳少数名族,以及其他汉字国家的文字,出现了GB13080,与GBK与GB2312不同的是,GB18030采用单字节、双字节和四字节三种方式对字符编码

编码方式范围:GB13080编码 > GBK编码 > GB2312编码

Unicode编码

同时各国都有自己的语言编码比如日文Shift_JIS,韩文Euc-kr等,又不可避免的会出现冲突,因此Unicode应运而生,ISO(国际标准化组织发明了”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode”)将所有的语言统一到一套编码里

ASCII和Unicode区别

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

新问题

Unicode支持所有语言,但相同的字母字符在ASCII中只占1个字符,而在Unicode中要占2个字符,因此Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上更消耗资源

UTF-8

别名(可变长的Unicode编码),UTF-8编码把一个unicode字符根据不同的数字大小编码成1-6个字节(英文字母占1字节,汉字通常3个字节,少数生僻字符才会被编码成4-6个字节)

UTF-8编码的好处

1.相比于Unicode当存在大量字母时,可节省存储空间
2.ASCII其实是UTF-8编码的一部分,因此兼容旧的只支持ASCII编码的历史遗留软件

实际使用

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码,比如:用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件

python2字符编码

查询编码类型
# 系统默认编码
import sys
sys.getdefaultencoding()

# 终端默认的编码(print时等)
import locale
locale.getdefaultlocale()
python2字符串类型

分别是str和unicode.他们有同一个基类basestring。str是plain string,其实应该称之为字节串,因为是每一个字节换一个单位长度。而unicode就是unicode string,这才是真正的字符串,一个字符(可能多个字节)算一个单位长度。

>>> us = u"严"
>>> us
u'\u4e25'
>>> print type(us), len(us)
<type 'unicode'> 1
>>> s = "严"
>>> s
'\xd1\xcf'
>>> print type(s), len(s)
<type 'str'> 2

第一,us、s的类型是不一样的;其二,同一个汉字,不同的类型其长度也是不一样的,对于unicode类型的实例,其长度一定是字符的个数,而对于str类型的实例,其长度是字符对应的字节数目

字符串对象输出
"""
__str__和__repr__的区别

__str__, 主要是用于展示,str(obj)或者print obj的时候调用,返回值一定是一个str 对象
__repr__, 是被repr(obj), 或者在终端直接打obj的时候调用
"""

>>> us = u'严'
>>> us
u'\u4e25'
>>> print us
严
str转unicode
unicode(str, encode)  # encode不传为系统默认编码
str.decode()
unicode转str
str.encode([encoding[, errors]])
# str.encode 这里的str是basestring,是str类型与unicode类型的基类

object.__str__(self)
# __str__是没有参数的,可以猜测,对于unicode类型,__str__函数一定也是使用了某种encoding来对unicode进行编码
unicode str utf-8关系

Python中使用decode()和encode()来进行解码和编码,以unicode类型作为中间类型。如下所示

decode     encode

str ---------> unicode --------->str

即str类型调用decode方法转换成unicode类型,unicode类型调用encode方法转换成str类型

str类型到底是什么

utf-8编码的str,与gbk编码的str,我们知道,一个汉字‘严’,可存储的编码格式可以是gbk(’xd1xcf’),也可以是utf-8(’xe4xb8xa5’),那么当我们在终端敲入这个汉字的时候,是哪一种格式呢?取决于***终端默认编码***

# windows上(默认终端编码为gbk):
>>> s = '严'
>>> s
'\xd1\xcf'

# Linux上(默认终端编码为utf-8):
>>> a = '严'
>>> a
'\xe4\xb8\xa5'

同样都是Python中的str类型,在不同的编码格式下,其二进制是不一样的。因此,其长度也是不一样的

要强调一下,unicode的二进制形式是与终端的编码格式无关的

看起来向unicode编码的字符串

某些情况下,我们打印出一个str类型,看到结果是’\u4e25’, 或者’u4e25’,对于这个字符串,是不是很眼熟,不错, ‘严‘的unicode编码就是u’u4e25’。仔细一看,只是在引号前面多了一个u(表示是一个unicode类型)。那么当我们看到一个’u4e25’的时候,怎么知道对应的汉字是什么?对于已知的这种格式的str,自然可以手动加一个u,然后在终端输出,但是如果是一个变量,需要自动转换成unicode呢,这个时候就可以使用python-specific-encodings中的unicode_escape

>>> s = '\u4e25'
\>>> s
'\\u4e25'
\>>> us = s.decode('unicode_escape')
\>>> us
u'\u4e25'
十六进制格式的字符串

有时候,也会看到类似这样的str,’\xd1\xcf’, 看起来也很熟悉,跟汉字“严”的gbk编码’xd1xcf’很像,区别在于前者多了一个‘’, 这样就无法解释成一个十六进制了。解决办法是python-specific-encodings中的string_escape

>>> s='\\xd1\\xcf'
\>>> s
'\\xd1\\xcf'
\>>> print s
\xd1\xcf
\>>> news = s.decode('string_escape')
\>>> news
'\xd1\xcf'
\>>> print news
严

Python3编解码

Python3 中不再有 str 和 unicode 字符类型的概念,取而代之的是 strbytes 两种字符类型。

str 是编码过的 unicode 文本字符,bytes 是编码前的字节序列。

Python3 在编码的处理上,它不再有所谓 unicode 字符串的概念,虽然也兼容 u"" 这样的写法,但这实际上也是一个 str 类型

>>> s = "我正在学Python"
>>> s '我正在学Python' 
>>> print(s) 我正在学Python 

>>> s_u = u"我正在学Python" 
>>> s_u '我正在学Python' 
>>> print(s_u) 我正在学Python 
>>> type(s) <class 'str'> 
>>> type(s_u) str'> 

>>> ss_u = "\u6211\u6b63\u5728\u5b66Python" 
>>> ss_u '我正在学Python' 
>>> print(ss_u) 我正在学Python

参考资料

https://www.liaoxuefeng.com/wiki/1016959663602400/1017075323632896

https://segmentfault.com/a/1190000021488157

https://www.huaweicloud.com/articles/b0d77c938584160b77c8f34a911f1841.html

https://bbs.huaweicloud.com/blogs/112325

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值