Python3 中的str和bytes类型

Python3最重要的新特性之一是:对字符串和二进制数据流做了明确的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python3不会以任何隐式的方式混用str和bytes,我们不能拼接字符串和字节流,也无法在字节流里搜索字符串(反之亦然),也不能将字符串传入参数为字节流(反之亦然)。

编码发展的历史

在bytes和str之前,需要先说说关于编码的发展。在计算机历史的早期,美国为代表的英语系国家主导了整个计算机行业,26个英文字母组成了多样的英语单词、语句、文章。因此,最早的字符编码规范是ASCII码,一种8位即一个字节码的编码规范,它可以涵盖整个英语系的编码需要。

什么是编码?编码就是把一个字符用一个二进制来表示。我们都知道,所有的东西,不管是英文、中文还是符号等等,最终存储在磁盘上都是010101这类东西。在计算机内部,读取和存储数据归根结底,处理的都是0和1组成的比特流。问题来了,人类看不懂这些比特流,如何让这些010101对认类变得可读呢?于是出现了字符编码,他是个翻译机,在计算机内部某个地方,透明的帮助我们将比特流翻译成认类可以直接理解的文字。对于一般用户,不需要知道这个过程是什么原理,是怎么执行的,但是对于程序员却是个必须搞清楚的问题。

以ASCII编码为例,它规定1个字节8比特位代表1个字符的编码,也就是"00000000"这么宽,一个一个字节的解读。例如:01000001表示大写字母A,有时候我们会用65这个十进制来表示A在ASCII中的编码。8个比特位,可以没有重复的最多表示2的8次方(255)个字符。

后来计算机得到普及,中文、日文、韩文等等国家的文字需要在计算机内表示,ASCII的255个远远不够。于是标准组织制定出了叫做Unicode的万国码,它规定任何一个字符(不管哪国的)至少以2个字节表示,可以更多。其中,英文字母就是用2个字节,而汉字是3个字节。这个编码虽然好,满足了所有人的要求,但是它不兼容ASCII,同时还占用较多的内存空间。因为在计算机世界更多的字符是英文字母,明明可以用1个字节就能够表示,非要用2个。

于是UTF-8(针对Unicode的可变长度字符编码)编码应运而生,它规定英文字母系列用1个字节表示,汉字用3个字节表示等等。因此,它兼容ASCII,可以节码早期的文档,很快UTF-8就得到了广泛的应用。在编码的发展历程中,我国还创造了自己的编码方式,例如:GBK、GB2312、BIG5,它们只局限在国内使用,不被国外认可。在GBK编码中,中文汉字占2个字节。

bytes和str之间的异同

回到bytes和str之上,bytes是一种比特流,它的存在形式是01010011这种。我们无论是在写代码,还是在阅读文章的过程中,肯定不会有人直接阅读这种比特流,他必须有一种编码方式,使得它变成有意义的比特流,而不是一堆晦涩难懂的01组合。因为编码方式的不同,对这个比特流的解读也会不同,对实际使用造成了很大的困扰。下面我们看看Python是如何处理这一系列编码问题的:

>>> s = "中文"
>>> s
'中文'
>>> type(s)
<class 'str'>
>>> b = bytes(s, encoding="utf-8")
>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>

从上面的例子可以看出,s是个字符串类型。Python的内置函数bytes()可以将字符串str类型转换成bytes类型,b实际上是一串01的组合,但为了在ide环境中让我们相对直观的观察,它被变现成了b'\xe4\xb8\xad\xe6\x96\x87'这种形式,开头的b表示这是一个bytes类型。\xe4是十六进制的表示方式,它占用1个字节的长度,因此"中文"被编码成utf-8后,我们可以数得出一共用了6个字节,每个汉字占用3个,这印证了上面的论述。在使用内置函数bytes()时,必须明确encoding的参数,不可省略。

我们都知道,字符串类型str里有一个encode()方法,它是从字符串向比特流的编码过程。而bytes类型恰好有个decode()方法,它是从比特流向字符串解码的过程。除此之外,我们查看Python的源码会发现bytes和str拥有几乎一摸一样的方法列表,最大的区别就是encode和decode。从实质上来说,字符串在磁盘上的保存形式也是01的组合,也需要编码和解码。如果,上面的阐述还不能让你搞清楚两者的区别,那么请记住下面几句话:

  • 1.在将字符串存入磁盘和从磁盘中读取的过程中,Python自动地帮助我们完成了编码和解码的工作,我们不需要关心其过程;
  • 2.使用bytes类型,实际上是告诉Python,不需要它帮我们自动地完成编码和解码的工作,而是用户自己手动进行,并指定编码格式;
  • 3.Python已经严格区分了bytes和str两种数据类型,我们不能在需要bytes类型参数的时候使用str参数,反之亦然,这点在读写磁盘文件时容易碰到;

在bytes和str的互相转换过程中,实际就是编码和解码的过程,必须显示地指定编码格式:

>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>
>>> res = str(b)
>>> res
"b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'"
>>> type(res)
<class 'str'>
>>> result = str(b, encoding="utf-8")
>>> result
'中文'
>>> type(result)
<class 'str'>

我们再把res转换成GBK编码的bytes类型:

>>> gbk_b = bytes(result, encoding="gbk")
>>> gbk_b
b'\xd6\xd0\xce\xc4'
>>> s = str(gbk_b, encoding="gbk")
>>> s
'中文'
>>> type(s)
<class 'str'>

Python 3中的str和bytes类型的更多相关文章

  1. python之路day06--python2/3小区别,小数据池的概念,编码的进阶str转为bytes类型,编码和解码

    python2#print() print'abc'#range() xrange()生成器#raw_input() python3# print('abc')# range()# input() = ...

  2. Python str 与 bytes 类型(Python2/3 对 str 的处理)

    本文均在 Python 3 下测试通过,python 2.x 会略有不同. 1. str/bytes >> s = '123' >> type(s) str >> ...

  3. Python str 与 bytes 类型 之间的转换

    bytes:字节数组,通常用它可以描述 “一个字符串”,只不过该字符串是  “bytes类型”,所以容易与str类型混淆,他们二者之间的转换: https://blog.csdn.net/lanchu ...

  4. Python中的str与bytes之间的转换的三种方法

    # bytes object b = b"example" # str object s = "example" # str to bytes sb = byt ...

  5. Python2和3版本对str和bytes类型的处理

    python2中字符串分为2种类型: 字节类型:str,字节类型,通过decode()转化为unicode类型 unicode类型:unicode ,通过encode转化为str字节类型 字节类型 和 ...

  6. 关于python2中的unicode和str以及python3中的str和bytes

    python3有两种表示字符序列的类型:bytes和str.前者的实例包含原始的8位值:后者的实例包含Unicode字符. python2中也有两种表示字符序列的类型,分别叫做str和unicode. ...

  7. python类中属性逗号引发的类型改变

    不注意点了个逗号引发了类型改变 [shangbl@newsvn ~]$ cat test.py class AB1: a="a" class AB12: a="a&quo ...

  8. python TypeError: must be str, not bytes错误

    TypeError: must be str, not bytes错误: 解答: 写文件处 f=open(filename, 'w')应该写为 open(filename, 'wb') 读文件时 f= ...

  9. 【Python】Python3中的str和bytes

    参考文章:Python 3的bytes/str之别 len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数 >>> len('ABC') 3 >& ...

随机推荐

  1. swift3.0通过响应链获取当前试图的控制器

    func parentViewController() -> UIViewController? { let n = next while n != nil { let controller = ...

  2. 人脸识别引擎SeetaFaceEngine简介及在windows7 vs2013下的编译

    SeetaFaceEngine是开源的C++人脸识别引擎,无需第三方库,它是由中科院计算所山世光老师团队研发.它的License是BSD-2. SeetaFaceEngine库包括三个模块:人脸检测( ...

  3. 后缀数组(SA)总结

    后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...

  4. 二、利用EnterpriseFrameWork快速开发Web系统(B/S)

    EnterpriseFrameWork框架实例源代码下载: 实例下载 本章通过一个开发实例来讲解Web系统的开发经过,以及会碰到的一些问题.实例功能就是业务系统中最常见的增.删.改.查来演示,用一个界 ...

  5. Appium+python的单元测试框架unittest(3)——discover(转)

    (原文:https://www.cnblogs.com/fancy0158/p/10047906.html) TestSuite套件可以添加很多个用例后运行,但是每个用例都需要调用addTest()函 ...

  6. 用python SMTP进行邮件发送

    import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart & ...

  7. JavaScript(js)处理的HTML事件、键盘事件、鼠标事件

    示例代码: HTML文件: <!DOCTYPE html><html lang="en"><head> <meta charset=&qu ...

  8. mybatis 加载配置文件的方法

    一.  使用sqlSessionFactory 的 mapperLocations 进行加载 <!-- SessionFactory --> <bean id="sqlSe ...

  9. Loadrunner教程--常用操做流程

    1loadrunner压力测试一般使用流程 1.1loadrunner压力测试原理 本质就是在loadrunner上模拟多个用户同时按固定行为访问web站点.其中固定行为在loadrunner中是通过 ...

  10. Python--matplotlib 绘图可视化练手--折线图/条形图

    最近学习matplotlib绘图可视化,感觉知识点比较多,边学习边记录. 对于数据可视化,个人建议Jupyter Notebook. 1.首先导包,设置环境 import pandas as pd i ...