浅析Python中bytes和str区别
本博转载自:Chown-Jane-Y的浅析Python3中的bytes和str类型
Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分。文本总是Unicode
,由str
类型表示,二进制数据则由bytes
类型表示。Python 3不会以任意隐式的方式混用str
和bytes
,你不能拼接字符串和字节流,也无法在字节流里搜索字符串(反之亦然),也不能将字符串传入参数为字节流的函数(反之亦然)。
下面让我们深入分析一下二者的区别和联系。
编码发展的历史
在谈bytes
和str
之前,需要先说说关于编码是如何发展的。。
在计算机历史的早期,美国为代表的英语系国家主导了整个计算机行业,26个英文字母组成了多样的英语单词、语句、文章。因此,最早的字符编码规范是ASCII码,一种8位即1个字节的编码规范,它可以涵盖整个英语系的编码需要。
编码是什么?编码就是把一个字符用一个二进制来表示。我们都知道,所有的东西,不管是英文、中文还是符号等等,最终存储在磁盘上都是01010101这类东西。在计算机内部,读取和存储数据归根结底,处理的都是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
编码应运而生,它规定英文字母系列用1个字节表示,汉字用3个字节表示等等。因此,它兼容ASCII
,可以解码早期的文档。UTF-8
很快就得到了广泛的应用。
在编码的发展历程中,我国还创造了自己的编码方式,例如GBK
,GB2312
,BIG5
。他们只局限于在国内使用,不被国外认可。在GBK
编码中,中文汉字占2个字节。
bytes和str之间的异同
回到bytes
和str
的身上。bytes
是一种比特流,它的存在形式是01010001110这种。我们无论是在写代码,还是阅读文章的过程中,肯定不会有人直接阅读这种比特流,它必须有一个编码方式,使得它变成有意义的比特流,而不是一堆晦涩难懂的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的组合,也需要编码解码。
如果,上面的阐述还不能让你搞清楚两者的区别,那么记住下面两几句话:
在将字符串存入磁盘和从磁盘读取字符串的过程中,Python自动地帮你完成了编码和解码的工作,你不需要关心它的过程。
使用
bytes
类型,实质上是告诉Python,不需要它帮你自动地完成编码和解码的工作,而是用户自己手动进行,并指定编码格式。Python已经严格区分了
bytes
和str
两种数据类型,你不能在需要bytes
类型参数的时候使用str
参数,反之亦然。这点在读写磁盘文件时容易碰到。
在bytes和str的互相转换过程中,实际就是编码解码的过程,必须显式地指定编码格式。
>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>
>>> s1 = str(b)
>>> s1
"b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'"
>>> type(s1)
<class 'str'>
>>> s1 = str(b, encoding='utf-8')
>>> s1
'中文'
>>> type(s1)
<class 'str'>
我们再把字符串s1,转换成gbk编码的bytes类型:
>>> s1
'中文'
>>> type(s1)
<class 'str'>
>>> b = bytes(s1, encoding='gbk')
>>> b
b'\xd6\xd0\xce\xc4'
浅析Python中bytes和str区别的更多相关文章
- python中bytes和str
1.python中bytes和str Python3 最重要的新特性大概要算是对文本(text)和二进制数据(binary data)作了更为清晰的区分 (1)Python 3.0使用文本和(二进制) ...
- 【转】浅析Python中的struct模块
[转]浅析Python中的struct模块 最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概 ...
- Python中__repr__和__str__区别
Python中__repr__和__str__区别 看下面的例子就明白了 class Test(object): def __init__(self, value='hello, world!'): ...
- 深入浅析python中的多进程、多线程、协程
深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...
- python中// 和/有什么区别
python中// 和/有什么区别 通常C/C++中,"/ " 算术运算符的计算结果是根据参与运算的两边的数据决定的,比如: 6 / 3 = 2 ; 6,3都是整数,那么结果也就是 ...
- python中bytes类型转换为str类型
使用的原因:基于URL解析报文的时候,要使用str类型,但是提供的确实bytes类型,报错: TypeError: must be str, not bytes 所以就把bytes类型转换为str类型 ...
- Python中is和==的区别
Python中有很多运算符,今天我们就来讲讲is和==两种运算符在应用上的本质区别是什么. 在讲is和==这两种运算符区别之前,首先要知道Python中对象包含的三个基本要素,分别是:id(身份标识) ...
- Python的bytes和str
Python和C的字符串 在Python 3 中,bytes单独作为一个类型,不再和str类型混在一起.关于字符串和字节,我想先回顾下C/C++ 在C/C++中,字符串是由char数组构成,每个元素是 ...
- 浅析Python中的struct模块
最近在学习python网络编程这一块,在写简单的socket通信代码时,遇到了struct这个模块的使用,当时不太清楚这到底有和作用,后来查阅了相关资料大概了解了,在这里做一下简单的总结. 了解c语言 ...
随机推荐
- JAVA发送HttpClient
http://bijian1013.iteye.com/blog/2310211 在发送HTTP请求的时候会使用到POST和GET两种方式,如果是传送普通的表单数据,我们直接将参数到一个Key-val ...
- Django如何把数据库里的html格式输出到前端
只需在HTML页面中加入{% autoescape off %}即可! {% autoescape off %} 需要显示的数据 (% endautoescap %}
- MapReduce:输出是一个文本文件,每一行第一个数字式行标,第二个数字是输入文件中每一行除行标外数字的平均值,且整数不保留小数,小数保留两位小数点
有时候你会遇到这样的问题:你有一个表格,给出了每个人在十二月,一月和二月的收入. 表格如下: 姓名 一月 二月 三月 楚乔 200 314 3500 宇文玥 2000 332 ...
- 深入理解JVM4——线程安全
浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的.其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序 ...
- C++结构体定义和C的区别
对于C来说,struct定义的结构体不是一种数据类型,所以每次声明的时候需要加上struct让编译器知道这是结构体,为了不每次都加上struct关键字,可以在定义结构体的时候加上typedef关键字: ...
- 混合开发的大趋势之 一个Android程序员眼中的 React.js 块级作用域 和 let
转载请注明出处:王亟亟的大牛之路 最近都有事干然后,快到月底了这个月给CSDN的博文也就两篇,想想也蛮多天没更了,那就来一篇. 老规矩,先安利:https://github.com/ddwhan012 ...
- strcpy的实现
// // Strcpy.c // libin // // Created by 李宾 on 15/8/20. // Copyright (c) 2015年 李宾. All rights reserv ...
- Apache顶级项目 Calcite使用介绍
什么是Calcite Apache Calcite是一个动态数据管理框架,它具备很多典型数据库管理系统的功能,比如SQL解析.SQL校验.SQL查询优化.SQL生成以及数据连接查询等,但是又省略了一些 ...
- mysql create database and user 新建数据库并为其创建专用账号
DROP DATABASE `wordpress`;------------------------------------------------------------------ CREATE ...
- MySql的数据库文件
找到mysql安装目录下的一个叫my.ini的文件用记事本或者其他的文本编辑器打开. 找到datadir这个字段,这个地址就是mysql数据库的地址 另附my.ini详解 Mysql my.ini 配 ...