Effective Python bytes 与 str 的区别
作者:小菠萝 发布时间:2021-07-11 16:52:13
1、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
2、Unicode 数据和二进制数据转换
把
Unicode
数据转换成二进制数据,必须调用 str 的encode
方法(编码)把二进制数据转换成
Unicode
数据,必须调用 bytes 的decode
方法(解码)调用这些方法时,可以明确指出字符集编码,也可以采用系统默认的方案,通常是 UTF-8
3、使用原始的 8 位值与 Unicode 字符串
使用原始的 8 位值与 Unicode 字符串时需要注意的两个问题:
该问题等价于:使用
bytes
和str
时需要注意的两个问题
3.1 问题一: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
3.2问题二:操作文件句柄时需要使用 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())
# 输出结果
ñò
这样也不会有异常了
需要注意:当前操作系统默认的字符集编码,Python 一行代码查看当前操作系统默认的编码标准
在 cmd 中执行:
> python3 -c 'import locale; print(locale.getpreferredencoding())'
UTF-8
来源:https://www.cnblogs.com/poloyy/p/15549664.html


猜你喜欢
- 前言静态文件是指 网站中的 js, css, 图片,视频等文件,本文主要给大家介绍了关于Django学习之静态文件调用的相关内容,分享出来供
- 本文实例讲述了Python Zip和Enumerate用法。分享给大家供大家参考,具体如下:Python 中的 Zipzip的作用:可以在处
- 入职第一家公司做开发的时候使用的项目版本管理工具是svn,公司内部搭建的服务器;在第二、第三家公司做开发的时候,使用的项目版本管理工具是Gi
- for循环只是一个多一点的代码,同时循环添加到它。而所涉及的一个循环的共同任务是: 设置一些计数器变量的初始值。 请检查条件语句是正确的。
- 1. 序列类型定义序列是具有先后关系的一组元素序列是一维元素向量,元素类型可以不同类似数学运算序列:S0,S1,…,S(n-1)元素间由序号
- 1)在service层和mapper层中写一个插入方法和查询方法;我们先写一个日志类;定义属性;并且要在数据库中建好表;package en
- 当前登入的用户以及他(她)的权限可以通过 RequestContext 在模板的context中使用。注意从技术上来说,只有当你使用了 Re
- 添加jar包 官网下载jar包idea导入jar包:检查官网下载jar包官网地址:MySQL :: Download Connec
- Go 命令Go语言自带有一套完整的命令操作工具,你可以通过在命令行中执行go来查看它们:图1.3 Go命令显示详细的信息这些命令对于我们平时
- 几个月前,我开始学习个人形象管理,从发型、妆容、服饰到仪表仪态,都开始做全新改造,在塑造个人风格时,最基础的是先了解自己属于哪种风格,然后找
- 1、如果之前已经安装我们先卸载一下yum -y remove php*2、由于linux的yum源不存在php7.x,所以我们要更改yum源
- 一 .概述SQL Server 将某些系统事件和用户定义事件记录到 SQL Server 错误日志和 Microsoft Windows 应
- 前言在线演示地址:http://haiyong.site/age-calculatorJavaScript提供了一些内置的日期和时间函数,有
- Python需要使用标识符给变量命名,其实标识符就是用于给程序中变量、类、方法命名的符号(简单来说,标识符就是合法的名称标识符需要以字母或下
- 1. APScheduler简介APscheduler全称Advanced Python Scheduler作用为在指定的时间规则执行指定的
- 判断一个数是否能被另一个整数整除是一个挺简单的问题,一般一个模运算就可以搞定了,懒惰的晓萌还是不想自己做,于是找到你帮他写代码,你就帮帮他吧
- --禁用 alter table tb disable trigger tir_name --啟用 alter table tb enabl
- 前言world:世界表格continent:大洲名称name:国家名称population:人口数量聚合函数介绍sum()求和函数avg()
- 当使用for语句循环(迭代)pandas.DataFrame时,简单的使用for语句便可以取得返回列名,因此使用重复使用for方法,便可以获
- 我们在 Bitcoin SV 上实现了一个数独游戏智能合约,利用之前介绍过的一种合约范式可以将游戏中寻找解题方案的过程外包上链。因为求解数独