Python 有两种类型可以表示字符序列

  • bytes:实例包含的是原始数据,即 8 位的无符号值(通常按照 ASCII 编码标准来显示)
  • str:实例包含的是 Unicode 码点(code point,也叫作代码点),这些码点与人类语言之中的文本字符相对应
a = b'h\x6511o'
print(list(a))
print(a) a = 'a\\u300 propos'
print(list(a))
print(a) # 输出结果
[104, 101, 49, 49, 111]
b'he11o' ['a', '\\', 'u', '3', '0', '0', ' ', 'p', 'r', 'o', 'p', 'o', 's']
a\u300 propos

Unicode 数据和二进制数据转换

  • 把  Unicode 数据转换成二进制数据,必须调用 str 的 encode 方法(编码)
  • 把二进制数据转换成 Unicode 数据,必须调用 bytes 的 decode 方法(解码)
  • 调用这些方法时,可以明确指出字符集编码,也可以采用系统默认的方案,通常是 UTF-8

使用原始的 8 位值与 Unicode 字符串时需要注意的两个问题

该问题等价于:使用 bytes 和 str 时需要注意的两个问题

问题一:bytes 和 str 的实例互不兼容

使用 + 操作符

# bytes+bytes
print(b'a' + b'1') # str+str
print('b' + '2') # 输出结果
b'a1'
b2
  • bytes + bytes,str + str 都是允许的
  • 但 bytes + str 会报错
# bytes+str
print('c' + b'2') # 输出结果
print('c' + b'2')
TypeError: can only concatenate str (not "bytes") to str

同类型之间也可以用二元操作符来比较大小

assert b'c' > b'a'

assert 'c' > 'a'

但 bytes 和 str 之间用二元操作符也会报错

assert b'c' > 'a'

# 输出结果
assert b'c' > 'a'
TypeError: '>' not supported between instances of 'bytes' and 'str'

判断 bytes 与 str 实例是否相等

两个类型的实例相比较总会为 False,即使字符完全相同

# 判断 str、bytes
print('a' == b'a') # 输出结果
False

格式化字符串中的 %s

两种类型的实例都可以出现在 % 操作符的右侧,用来替换左侧那个格式字符串(format string)里面的 %s

但是!如果格式字符串是 bytes 类型,那么不能用 str 实例来替换其中的 %s,因为 Python 不知道这个 str 应该按照什么字符集来编码

# %
print(b'red %s' % 'blue') # 输出结果
print(b'red %s' % 'blue')
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'

但是!反过来却可以,如果格式字符串是 str 类型,则可以用bytes 实例来替换其中的 %s,但结果可能不是预期结果

# %
print('red %s' % b'blue') # 输出结果
red b'blue'
  • 这样会让系统在 bytes 实例上面调用 __repr__ 方法
  • 调用结果替换格式字符串里的 %s,因此程序会直接输出 b'blue',而不是输出 blue

问题二:操作文件句柄时需要使用 Unicode 字符串操作

不能使用原始的 bytes

向文件写入二进制数据会报错

# 写入二进制数据
with open('test.txt', "w+") as f:
f.write(b"\xf1\xf2") # 输出结果
f.write(b"\xf1\xf2")
TypeError: write() argument must be str, not bytes
  • 报错是因为 w 模式必须以文本模式写入
  • 将模式改成 wb 即可正常写入二进制数据
with open('test.txt', "wb") as f:
f.write(b"\xf1\xf2")

读取文件中二进制数据

with open('test.txt', "r+") as f:
f.read() # 输出结果
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 0: invalid continuation byte
  • 报错是因为 r 模式必须以文本模式读取
  • 以文本模式操纵文件句柄时,系统会采用默认的文本编码方案处理二进制数据
  • 所以,上面那种写法会让系统通过 bytes.decode 把这份数据解码成 str 字符串,再用 str.encode 把字符串编码成二进制值
  • 然而对于大多数系统来说,默认的文本编码方案是UTF-8,所以系统很可能会把 b'\xf1\xf2\xf3\xf4\xf5' 当成  UTF-8 格式的字符串去解码,于是就会出现上面那样的错误

将模式改成 rb 即可正常读取二进制数据

with open('test.txt', "rb") as f:
print(b"\xf1\xf2" == f.read()) # 输出结果
True

另一种改法,设置 encoding 参数指定字符串编码

with open('test.txt', "r", encoding="cp1252") as f:
print(f.read()) # 输出结果
ñò

这样也不会有异常了

重点

需要注意当前操作系统默认的字符集编码

https://www.cnblogs.com/poloyy/p/15536156.html

Effective Python(3)- 了解 bytes 与 str 的区别的更多相关文章

  1. bytes和str的区别与转换

    bytes和str的区别 1.英文 b'alex'的表现形式与str没什么两样 2.中文 b'\xe4\xb8\xad'这是一个汉字在utf-8的bytes表现形式 3.中文 b'\xce\xd2'这 ...

  2. bytes 与 str的区别以及装换

    bytes 和 str 的区别: bytes 存储字节( 通常值在 range(0, 256)) str 存储unicode字符( 通常值在0~65535) bytes 与 str 的转换 编码(en ...

  3. python中的bytes和str类型

    经过一上午的查找资料.大概理清楚了bytes类型和str类型的区别. bytes类型和str类型在呈现形式有相同之处,如果你print一个bytes类型的变量,会打印一个用b开头,用单引号括起来的序列 ...

  4. Python 3中bytes和str的分别

    最近把一段py2的代码转换到py3的代码,结果运行到向socket中写数据的代码部分出现了'str' does not support the buffer interface这样一个错误. 一番搜索 ...

  5. python中bytes和str

    1.python中bytes和str Python3 最重要的新特性大概要算是对文本(text)和二进制数据(binary data)作了更为清晰的区分 (1)Python 3.0使用文本和(二进制) ...

  6. 【Python】Python3中的str和bytes

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

  7. 浅析Python中bytes和str区别

    本博转载自:Chown-Jane-Y的浅析Python3中的bytes和str类型 Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示, ...

  8. Python的bytes和str

    Python和C的字符串 在Python 3 中,bytes单独作为一个类型,不再和str类型混在一起.关于字符串和字节,我想先回顾下C/C++ 在C/C++中,字符串是由char数组构成,每个元素是 ...

  9. python编程之字符bytes转换str问题

    之前学习bytes转换str的时候,场景比较简单,这次是python中使用subprocess模块输出Linux下的执行命令的结果,默认是bytes类型,因此输出的结果并不是我们想要的,bytes的输 ...

随机推荐

  1. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...

  2. [gdoi2018 day1]小学生图论题【分治NTT】

    正题 题目大意 一张随机的\(n\)个点的竞赛图,给出它的\(m\)条相互无交简单路径,求这张竞赛图的期望强联通分量个数. \(1\leq n,m\leq 10^5\) 解题思路 先考虑\(m=0\) ...

  3. T183637-变异距离(2021 CoE III C)【单调栈】

    正题 题目链接:https://www.luogu.com.cn/problem/T183637 题目大意 给出\(n\)个二元组\((x_i,y_i)\),求最大的 \[|x_i-x_j|\time ...

  4. kendoUI 多选下拉列表 kendoMultiSelect

    问题1:被重复渲染 点击新增按钮----弹出模态框 多选下拉列表在多选框中只是初始化过一次.但是每次点击新增后  发现 多选下拉列表 被重复渲染了 解决方案 在 新增时  先将其父元素div中  的s ...

  5. 数据结构与算法——迪杰斯特拉(Dijkstra)算法

    tip:这个算法真的很难讲解,有些地方只能意会了,多思考多看几遍还是可以弄懂的. 应用场景-最短路径问题 战争时期,胜利乡有 7 个村庄 (A, B, C, D, E, F, G) ,现在有六个邮差, ...

  6. centos8安装MySQL8——通过yum

    centos8上通过yum安装MySQL,过程简单,不易出错 1.检查系统是否已安装MySQL相关,如果有则全部清除干净 #列出MySQL相关的安装包 rpm -qa | grep mysql #依次 ...

  7. bzoj1834 ZJOI2010网络扩容(费用流)

    给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容费用. 其中\(n ...

  8. 3DGIS开发使用的开源项目

    gdal proj4 vcglib assimp libjpg libpng osg libtess2 cesiumjs glm

  9. 纯前端H5小应用_localStorage存储

    开发缘由[需求发现和分析] 想要送朋友一个礼物,但是想了想,街上买的东西,em~,我们这样的猿确实不会选礼物啊,由此就想利用自己手中的工具和知识做点有用的东西吧,抱枕是礼物,钢笔是礼物,电子产品也是礼 ...

  10. python join的用法

    joinn其实就相当于用某个字符串来拼接列表或者元组中的元素 当然也可以将字符串以某一个str拼接起来 得出的结果自然也是字符串 ex1: results: 实例用处: 当我们从某个文件中读出内容时, ...