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. 20145226夏艺华 EXP5 MSF基础应用

    实践目标 · 掌握metasploit的基本应用方式. · 具体需要完成 (1)ms08_067; (2)ms11_050: (3)Adobe (4)成功应用任何一个辅助模块. 报告 本次实验一共用到 ...

  2. 封印解除:如何在Win10家庭版中启用组策略

    @echo off pushd "%~dp0" *.mum >List.txt *.mum >>List.txt for /f %%i in ('findstr ...

  3. 【LG3835】可持久化平衡树

    [LG3835]可持久化平衡树 题面 洛谷 解法一 参考文章 rope大法好 \(rope\)基本操作: #include<ext/rope> using namespace __gnu_ ...

  4. angular中的$http服务

    $http是ng内置的一个服务.是简单的封装了浏览器原生的XMLHttpRequest对象. 写法1 $http({ method: "GET", url: 'data.json' ...

  5. STM32L431驱动带UC1698芯片调试记录

    1, 数据线连接方式,这次使用的是8080格式的接口,如下 2. 主要是信号和数据引脚 DATA0-DATA7  并口的数据 RST 复位信号 WR 写信号 RD 读信号 C/D 数据还是命令 CS片 ...

  6. [cogs347]地震

    COGS:地震(平衡树) COGS上一道题...文件名是equake 还是又打了一遍板子... 加个lazy标记就行了... 注意查询时先下传标记(lazy) // It is made by XZZ ...

  7. 【索引】MySQL索引

    一.索引的定义及作用 1. 二.索引的创建及删除 1.1查看表的索引 show index from tblname; 1.2.创建索引 1.22创建普通索引 ALTER TABLE `table_n ...

  8. SQL Server 2008 R2 链接 Oracle 10g

    首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1.“MSDAORA”访问接口是由Microsoft OLE DB Provi ...

  9. python基础数据类型补充

    python_day_7 一. 今日主要内容: 1. 补充基础数据类型的相关知识点 str. join() 把列表变成字符串 列表不能再循环的时候删除. 因为索引会跟着改变 字典也不能直接循环删除.把 ...

  10. Docker--从安装到搭建环境

    docker 1. ubuntu下安装docker 安装docker有两种方法: 一种是用官方的bash脚本一键安装. 直接一条命令就解决了: $ curl -sSL https://get.dock ...