Python 3 字符串中的 STR和Bytes 究竟有什么区别?

作者 | veelion

责编 | 胡巍巍

Python2的字符串有两种:str和Unicode,Python3的字符串也有两种:str和Bytes。Python2的str相当于Python3的Bytes,而Unicode相当于Python3的Bytes。

Python2里面的str和Unicode是可以混用的,在都是英文字母的时候str和unicode没有区别。

而Python3严格区分文本(str)和二进制数据(Bytes),文本总是Unicode,用str类型,二进制数据则用Bytes类型表示,这样严格的限制也让我们对如何使用它们有了清晰的认识,这是很棒的。

Python2 和 Python3 的区别

通过以下代码我们认识以下Python2和Python3的字符串混用情况:

# Python2中:In[1]:'a'== u'a'Out[1]: True

In[2]:'a'inu'a'Out[2]: True

In[3]:'编程'== u'编程'/usr/local/bin/ipython:1: UnicodeWarning: Unicode equal comparison failedtoconvert both argumentstoUnicode - interpreting themasbeing unequal#!/usr/bin/pythonOut[3]: False

In[4]:'编程'inu'编程'---------------------------------------------------------------------------UnicodeDecodeError Traceback (most recent call last)

in()

---->1'编程'inu'编程'

UnicodeDecodeError:'ascii'codec can't decode byte 0xe7 in position 0: ordinal not in range(128)

# Python3中:

In [1]: 'a' == b'a'Out[1]: False

In [2]: 'a' in b'a'---------------------------------------------------------------------------TypeError Traceback (most recent call last)

in ()

----> 1 'a' in b'a'

TypeError: a bytes-like object is required, not 'str'

以上代码可以看到,Python2中str和Unicode在都是ASCII码时混用没区别,因为Unicode的ASCII区域的值跟str的ASCII是一样的;而对应非ASCII区域(比如中文),二者又不一样了。

可以看到Python2抛出了Unicode Decode Error的异常,相信这也是很多人处理文本时遇到过的错误;‘编程’在str类型时长度是6,而在Unicode时是2。不同字符的不同表现,让Python2的str和Unicode显得扑朔迷离。

在Python3中,严格区分了str和Bytes,不同类型之间操作就会抛出Type Error的异常。

上面用示例阐述了Python2和Python3中字符串的不同,下面主要讲Python3中的字符串。

str和bytes之间的转换

一图胜千言:

str和bytes的相互转换

str.encode(‘encoding’) -> bytes

bytes.decode(‘encoding’) -> str

Encoding指的是具体的编码规则的名称,对于中文来说,它可以是这些值: ‘utf-8’, ‘gb2312’, ‘gbk’, ‘big5’ 等等。

不知道你有没有注意到上图中str矩形要比Bytes矩形短,表示同样的内容,str的长度要小于或等于Bytes的长度,你可以考虑一下原因(参考Unicode、UTF-8的编码规则)。

下面看看具体代码理解一下str和Bytes的相互转换:

In[16]: a ='T恤'In[17]: a

Out[17]:'T恤'In[18]: len(a)

Out[18]:2In[19]: b = a.encode('utf8')

In[20]: b

Out[20]: b'T\xe6\x81\xa4'In[21]: a == b

Out[21]: FalseIn [22]: c = a.encode('gbk')

In[23]: c

Out[23]: b'T\xd0\xf4'In[24]: b == c

Out[24]: FalseIn [25]: a == c

Out[25]: False

上面str和Bytes之间的转换是针对文本内容的,要是其它二进制内容(比如,图片)时,Bytes就不能decode成str了,看以下代码的异常:

In[29]: img = open('str-bytes.jpg','rb').read()

In[30]:type(img)

Out[30]: bytes

In[31]: img.decode('utf8')

---------------------------------------------------------------------------

UnicodeDecodeError Traceback (most recent call last)

in()---->1img.decode('utf8')UnicodeDecodeError:'utf-8'codec can't decode byte 0xff in position 0: invalid start byte

因为图片中的二进制数据不符合文本数据的UTF-8编码规则。

上面获得图片数据时,我们用到了open()来读取文件,文件存储的无非是文本和二进制这两种格式,读写文件时也有分清楚编码:

In[32]: open('z.txt','w').write('T恤')

Out[32]:2In[33]: open('z.txt','w').write(img)

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

in()

---->1open('z.txt','w').write(img)

TypeError:write() argument must be str,notbytes

In[34]: open('z.txt','wb').write(img)

Out[34]:12147

读写二进制数据(如图片)时,要加’rb’参数,b代码Binary(二进制)。读写文本数据时,一般加’b’,open()会自动转换Bytes到str。

总结一下

Python3里面的str是在内存中对文本数据进行使用的,Bytes是对二进制数据使用的。

str可以encode为Bytes,但是Bytes不一定可以decode为str。实际上Bytes.decode(‘latin1’)可以称为str,也就是说decode使用的编码决定了decode()的成败,同样的,UTF-8编码的Bytes字符串用GBK去decode()也会出错。

Bytes一般来自网络读取的数据、从二进制文件(图片等)读取的数据、以二进制模式读取的文本文件(.txt, .html, .py, .cpp等)。

作者:veelion,具有十年开发经验,主要使用Python、C++语言,从事网络爬虫、搜索引擎、自然语言理解处理等领域的研发工作。

声明:本文为作者投稿,版权归对方所有。

微信改版了,

想快速看到CSDN的热乎文章,

赶快把CSDN公众号设为星标吧,

打开公众号,点击“设为星标”就可以啦!

2018 AI开发者大会

AI工程师必备大会

2018 AI开发者大会是一场由中美人工智能技术高手联袂打造的AI技术与产业的年度盛会!我们只讲技术,拒绝空谈!

这里有10场技术专题论坛:计算机视觉、数据分析、机器学习、知识图谱、智慧金融、智能驾驶、语音技术、智慧医疗、机器学习工具、自然语言处理。

还有15+硅谷实力讲师团、80+AI领军企业技术核心人物、100+技术&大众实力媒体、1500+AI专业开发者

点击下方「海报」,快速获取大会更多信息,并获得最低折扣票!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181014A0I0QA00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券