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. Caliburn.Micro - IResult and Coroutines

    IResult and Coroutines 翻译[三台]:网址[http://home.cnblogs.com/u/3Tai/] Previously, I mentioned that there ...

  2. Tomcat设置是否可以上传文件到服务器

    今天,我做的一个点菜项目要求做一个添加菜品,把菜品的路径保存进数据库,然后将菜品的图片保存进tomcat相应的目录中. 一开始,我在客户端写的代码是直接向tomcat的目录写文件,但是会出现403错误 ...

  3. day9 匿名函数 lambda

    1. list列表排序 #### sort排序 nums = [,,,,,] nums.sort() print(nums) ### 结果 [, , , , , ] ######## 逆序 In [] ...

  4. angularJS ng-repeat中的directive 动态加载template

    有个需求,想实现一个html组件,传入不同的typeId,渲染出不同的表单元素. <div ng-repeat="field in vm.data"> <magi ...

  5. 【MYSQL安装】mysql 5.6在centos6.4上的安装

    1.卸载系统自带的mysql [root@zhangmeng ~]# rpm -qa |grep mysql mysql-libs--.el6_3.x86_64 [root@zhangmeng ~]# ...

  6. xxl_job springboot改造

    代码地址:https://gitee.com/sharehappy/xxl_job_springboot 官方文档:https://github.com/xuxueli/xxl-job/blob/ma ...

  7. testNG-失败用例重跑机制

    下面简单介绍下testNG的失败重跑的实现方法: 1.首先编写一个类,实现IRetryAnalyzer类,重写其中的retry方法. public class TestNGRetry implemen ...

  8. 用python SMTP进行邮件发送

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

  9. Unity利用Share SDK实现QQ、微信及微博第三方登录及定制内容分享(附代码)

    最近因为公司的项目需要添加一些实用性的功能,需要添加第三方登录及分享,采用的是Mob的SDK,可以先到其官网下载对应的SDK 点击这里,为了方便后期进行数据统计和分析,所以可以先添加一个应用,添加成功 ...

  10. Atom 插件 Sync Settings 备份与恢复

    当使用 Atom IDEA.随着使用的越来越多,安装的插件也越来越多,一旦电脑重装后需要复原开发环境,这将是一件比较头疼的事.「Sync Settings」插件可以帮助我们解决这个问题. 操作流程 安 ...