欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

程序员文章站 2022-07-12 17:54:46
...

 本节我们接着讲bytes类型,上一节内容:

免费****!零基础学Python系列(7) - 数据类型之bytes(上)

本节课程的视频和实例源码下载方式:点击->我的主页,查看个人简介。

我尽量坚持每日更新一节。


  • 字符编码

Python2.x的乱码问题一直被程序员所诟病,虽然Python3.X大体上已经解决了这个问题,但是作为入门python的基础,你还是需要把字符编码问题搞得非常清楚,否则你会被各种“乱码”搞崩溃。下面是引用的知乎上面一个回答,挺有意思:

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

 

  • 什么是字符编码呢?

我们知道计算机是使用01这样的二进制串来存储数据的,这里的数据不仅仅是数字,而是所有数据,包括图片、视频、音频、文字等等。所以,我们需要有一个规则,来定义这些数据和二进制之间如何转换。

字符编码,就是一套标准(事实上有若干套标准),根据这些标准,我们将字符和二进制双向转换。

最早的字符编码标准,叫做ASCII码。

 

  • ASCII

计算机技术起源于美国,所以最早的字符编码标准ASCII(American Standard Code for Information Interchange)也是老美根据他们的语言体系制定的。在英语的世界里面,26个小写字母、26个大写字母、若干个标点符号、一些控制符号等就可以表示所有字符。

下面就是全部的ASCII编码,一共就只有256个符号的编码定义:

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

 

第一列是字符对应的十进制数值,比如001d;

第二列是字符对应的十六进制数值,比如0Ah;

第三列是对应的字符;

0~31还定义了第四列,用于表示一些特殊的控制符,比如008d对应的是退格(Backspace),我们敲键盘的Backspace退格键,就会产生008d这个数值在计算机中传递。

最早 ASCII 只定义了128个字符编码,包括96个显示字符和32个控制符号,一共128个字符,只占用了一个字节8bit位中的低7位。然而随着计算机慢慢普及,一些西欧字符在字符集中无法被表示,于是就有了下面那种扩展ASCII表,将字符集扩展到了256个。

 

  • GB2312\GBK

ASCII码标准的指定可没有考虑中文的问题,于是当计算机在中国以及亚洲国家出现以后,中文编码成了一个问题。为了解决这个问题,我国制定了自己的字符编码标准GB2312(GB-国标)。GB2312收录的汉字基本覆盖了我们使用的绝大多数场景,但是对于繁体字和少数民族文字无法处理。于是后来又制定了GBK标准(K-扩展),GBK在GB2312基础上制定,它除了收录27484个汉字以外,还收录了藏文、蒙文、*文等少数民族文字。

GBK采用两个字节来表示中文,同时它也兼容ASCII标准,当使用ASCII字符时可以自动转换为一个字节来表示。

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

 

  • Unicode

不同国家都有自己的语言和文字,如果大家都自己制定自己的字符编码规范,那它们之间如何互通呢?为了解决这个问题,科学家们发明一种统一的字符编码-unicode(UniversalMultiple-OctetCodedCharacterSet,简称UCS),它几乎囊括了人类所有语系字符的编码。Unicode同样也是兼容ascii码的。

Unicode采用2字节编码,这一标准的2字节形式叫做UCS-2。但是我们知道2字节最多只能表示65535个字符编码,这对于一些特殊语系来说是完全不够的,比如中文字符就有几万个。所以,unicode还有一种4字节的形式,叫做UCS-4,它有足够的空间可以定义人类所有的文字符号。

 

  • UTF-8

Unicode是一个字符集,它仅定义了不同符号对应的编码值。但是这个字符该如何存储呢?对于ascii码,我们可以统一采用一个字节来存储不同的字符。Unicode字符也可以这样操作,但这样会带来一个存储效率的问题。

比如字符“a”,它对应的编码是61,一个字节就可以表示。如果我们采用4字节表示,那么有3个字节就浪费掉了。在英语系国家,这种浪费就显得非常严重,接近3/4的存储性能损失,这是不能被接受的。

基于这个原因,出现了各种unicode的实现方法,最著名的是UTF-8。

UTF-8以一个字节(8比特位)为一个编码单位,并且它是变长的。对于不同的unicode字符,它会采用不同的字节长度来存储。这样就可以大大提升存储性能。

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

 

比如汉字“中”,它的unicode表示和utf-8编码如下:

 

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

除了UTF-8,还有UTF-16,同理,它是以16比特-2字节为一个编码单位。

 

字符乱码的原因,基本都是字符编码不一致导致的。Python2默认采用ascii码,中文字符默认是不能转换的,所以我们在python2代码中如果涉及中文字符,必须在代码文件一开始就进行字符编码的声明:

# -*-coding:utf-8-*-

Python2的字符编码问题备受诟病。在python3中,默认编码改成了utf-8,所以我们不声明编码类型,也是可以正常支持中文字符的。

字符编码需要端到端保持一致,不管是存储、计算、传输等环节都要设置一致,比如我们代码处理时采用的字符编码必须和数据库存储的编码方式一致。否则很容易出现乱码。

 

  • Bytes和string之间的转换

Bytes和string之间的转换,其本质就是一个字符编码的过程。Python3提供了encode和decode方式来实现两者之间的灵活转换,其过程如下图:

免费****!零基础学Python系列(8) - 数据类型之bytes(下)

Encode是字符编码过程,将字符转换为指定的编码,并以bytes类型存储;

Decode则相反,将bytes值转换为对应的字符。

语法如下:

str.encode(encoding='UTF-8',errors='strict')

str.decode(encoding='UTF-8',errors='strict')

 

encoding -- 要使用的编码方式,如"UTF-8"

errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError 其他可能得值有 'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 以及通过 codecs.register_error() 注册的任何值。

 

下面是一个编解码的例子:

#  author: Tiger,    wx ID:tiger-python

# file: ./6/6_3.py

# bytes 按照16进制输出,强制不ascii转码
def trans(s):
    return "b'%s'" % ''.join('\\x%.2x' % x for x in s)


# 字符编码
encstr_1 = 'tiger-python'
encbytes_1 = encstr_1.encode('utf-8')
print(trans(encbytes_1))
print(encbytes_1.decode('utf-16'))  # 编码方式不一致,造成乱码
print(encbytes_1.decode('utf-8'))

输出为:

b'\x74\x69\x67\x65\x72\x2d\x70\x79\x74\x68\x6f\x6e'

楴敧祰桴湯

tiger-python

如果编解码的编码方式不一致,则出现乱码。

 

好了,下节我们继续学习python的其它数据类型。


本节课程的视频和实例源码下载方式:点击->我的主页,查看个人简介。

我尽量坚持每日更新一节。

相关标签: 0基础学python****